Как шаблонный класс разрешает перегруженную функцию, не являющуюся членом, которая вызывается для одного из ее типов? - PullRequest
1 голос
/ 01 февраля 2020

В следующем примере я создал фиктивный класс Container для произвольного типа. Вызов сравнения () для Контейнера вызывает сравнение () для объекта Value, хранящегося внутри. Как функция сравнения (), перегруженная для значения, разрешается в Container<Value>, если она объявлена ​​позднее и не является функцией-членом значения?

Код:

template<typename T>
class Container
{
public:
    Container(T value) : element(value) {}
    T element;
};

template<typename T>
int compare(Container<T> const& first, Container<T> const& second)
{
    return compare(first.element, second.element);
}

class Value
{
public:
    Value(int value) : value(value) {}
    int value;
};

int compare(Value const& first, Value const& second)
{
    if (first.value < second.value)
        return -1;
    else if (first.value > second.value)
        return 1;
    return 0;
}

int main()
{
    auto l1 = Container<Value>(1);
    auto l2 = Container<Value>(1);
    auto l3 = Container<Value>(2);

    cout << compare(l1, l2) << endl;
    cout << compare(l1, l3) << endl;
}

Вывод (как и ожидалось) ):

0
-1

Ответы [ 2 ]

0 голосов
/ 01 февраля 2020

Это потому, что зависимый от аргумента поиск (ADL).

Два аргумента вызова compare(first.element, second.element) имеют тип Value, поэтому выполняется поиск во всем включающем пространстве имен Value, т. Е. Глобальном пространстве имен, и перегрузке compare для Value найдено.

Если вы замените Value на базовый тип, например, int, тогда ADL не будет и код не будет работать:

template<typename T>
class Container
{
public:
    Container(T value) : element(value) {}
    T element;
};

template<typename T>
int compare(Container<T> const& first, Container<T> const& second)
{
    return compare(first.element, second.element); // error: no matching function for call to 'compare(const int&, const int&)'
}

int compare(int first, int second)
{
    if (first < second)
        return -1;
    else if (first > second)
        return 1;
    return 0;
}

int main()
{
    auto l1 = Container<int>(1);
    auto l2 = Container<int>(2);

    compare(l1, l2);
}
0 голосов
/ 01 февраля 2020

Шаблоны разрешаются только тогда, когда они создаются, поэтому ваш compare Value метод должен быть объявлен до main, а не до compare Container метода

...