Почему std:: sort не принимает классы сравнения, объявленные внутри функции

Я работал, писал Компараторы в функции (чтобы позже, когда я решил, где лучше), и заметил эту особенность. Я подумал об этом некоторое время и понял, что не понимаю, почему код не будет компилироваться, если я использую внутренние компараторы, но внешний - в порядке.

Любые объяснения?

Жгут проводов Quick Test:

#include <iostream>
#include <vector>
#include <algorithm>

class CompareMe
{
 public:
    CompareMe(int in) : toCompare(in){}
    int toCompare;
};

class Comparators
{
public:
    bool operator()(CompareMe * first, CompareMe * second)
    {
        return first->toCompare < second->toCompare;
    }
};

class ComparatorsOuter : public Comparators{};

int main()
{
    class ComparatorsInner : public Comparators{};

    std::vector<CompareMe *> compares;
    compares.push_back(new CompareMe(0));
    compares.push_back(new CompareMe(1234));
    compares.push_back(new CompareMe(163));
    compares.push_back(new CompareMe(6));
    compares.push_back(new CompareMe(12));

    //This works, and properly sorts the array
    ComparatorsOuter comparator;
    std::sort(compares.begin(), compares.end(), comparator);

    //Uncomment out the sort below and it will not compile.
    ComparatorsInner comparatorInner;
    //std::sort(compares.begin(), compares.end(), comparatorInner);

    std::vector<CompareMe *>::iterator it;
    for(it = compares.begin(); it != compares.end(); ++it)
    {
        std::cout << (*it)->toCompare << std::endl;
    }
}

ошибка: нет соответствующей функции для вызова "sort(__gnu_cxx::__normal_iterator<CompareMe**, std::vector<CompareMe*, std::allocator<CompareMe*> > >, __gnu_cxx::__normal_iterator<CompareMe**, std::vector<CompareMe*, std::allocator<CompareMe*> > >, main()::ComparitorInner&)"

Ответ 1

В С++ 03 аргументы шаблона не могут иметь внутренней связи:

[C++03: 14.6.4.2/1]: Для вызова функции, который зависит от параметра шаблона, если имя функции является неквалифицированным идентификатором, но не идентификатором шаблона, функции-кандидаты обнаруживаются с использованием обычных правил поиска (3.4.1, 3.4. 2), за исключением того, что:

  • Для части поиска, использующей поиск неквалифицированного имени (3.4.1), найдены только объявления функций с внешней привязкой из контекста определения шаблона.
  • Для части поиска с использованием связанных пространств имен (3.4.2) найдены только объявления функций с внешней связью, найденные либо в контексте определения шаблона, либо в контексте создания шаблона.

[..]

Это было изменено (вопрос # 561: "Внутренние функции привязки в зависимом поиске имен" ) в С++ 11:

[C++11: C.2.6]: 14.6.4.2
Изменить: разрешить зависимые вызовы функций с внутренней связью
Обоснование: Слишком ограниченные, упрощают правила разрешения перегрузки.

в результате:

[C++11: 14.6.4.2/1]: Для вызова функции, зависящего от параметра шаблона, функции-кандидата найдены с использованием обычных правил поиска (3.4.1, 3.4.2, 3.4.3), за исключением того, что:

  • Для части поиска, использующей поиск неквалифицированного имени (3.4.1) или поиск квалифицированного имени (3.4.3), отображаются только объявления функций из контекста определения шаблона.
  • Для части поиска с использованием связанных пространств имен (3.4.2) найдены только объявления функций, найденные в контексте определения шаблона или контекста создания шаблона.

[..]

(Определите недостающую "внешнюю привязку" ).

Поскольку ваш main()::ComparitorInner& имеет внутреннюю привязку, а для экземпляра std::sort требуется, чтобы этот тип был параметром шаблона (хотя и выведенным), ваш код действителен только в С++ 11.

Ответ 2

Ваш код в С++ 11 хорош; было ограничение об использовании локальных типов в качестве аргументов шаблона в С++ 03.