Кажется, мое явное создание экземпляра класса шаблона не работает - PullRequest
3 голосов
/ 25 апреля 2011

Я написал короткую программу для проверки явного создания экземпляра класса шаблона следующим образом:

#include <iostream>

template <class T>
struct less_than_comparable {
    friend bool operator>=(T const& a, T const& b) {
        return !(a < b);
    }
};

class Point {
    friend bool operator<(Point const& a, Point const& b) {
        return a.x_ < b.x_;
    }

public:
    Point(int x) : x_(x) {}

private:
    int x_;
};

template struct less_than_comparable<Point>; 
//Here I explicitly instantiate a template class expecting that 
//less_han_comparable<Point> would export opeartor>=() for class Point to the global
//namespace, and then the p1 >= p2 statement will work as expected.

int main() {
    using namespace std;

    Point p1(1), p2(2);
    cout << (p1 < p2) << endl;
    cout << (p1 >= p2) << endl; //But I have a compiler error here saying that 
                                //no match for ‘operator>=’ in ‘p1 >= p2’
}

Я знаю, что если я унаследую Point от less_than_comparable, код пройдет компиляцию. Но мой вопрос - почему это не работает, если я использую явное создание экземпляров? Я использую G ++ 4.4.5, работающий на Ubuntu 10.04. Любые комментарии будут оценены. Спасибо.

Ответы [ 4 ]

2 голосов
/ 25 апреля 2011

Проблема в том, что функции друзей, определенные внутри классов, подобных классам, не внедряются во вложенное пространство имен.

Принцип, на который вы ссылаетесь, называется "внедрение имен друзей", но этобыл заменен в текущем стандарте C ++ на «ADL» ( Аргумент-зависимый поиск , также называемый Koenig Lookup ).ADL проверяет все пространства имен, связанные с типами параметров функции, для сопоставления функции.

В вашем случае, когда вы вызываете operator>= в p1 >= p2 (то есть operator>=(p1, p2);).ADL ищет соответствующую функцию в пространстве имен Point, но Point не имеет такой функции.

Если вы наследуете Point от less_than_comparable, operator>= становится частью пространства имен Point и ADL может найти его здесь.

Вы можете проверить, не происходит ли инъекция имени друга здесь .

1 голос
/ 25 апреля 2011

Код не работает, потому что Point не является классом шаблона, в котором вы определили operator >=.Если вы хотите скомпилировать этот код, определите также operator >= в классе Point.Обратите внимание, что p1 и p2 не связаны с less_than_comparable.

В качестве примечания, почему вы определили оператор для оператора «больше чем равно» в имени less_than_comparable?

1 голос
/ 25 апреля 2011

Явное создание экземпляров - это просто способ заставить компилятор скомпилировать конкретный шаблон в этом модуле перевода - это никак не влияет на поиск имен.

Чтобы получить то, что вам нужно, вы могли быпример:

class Point : public less_than_comparable<Point> {
0 голосов
/ 25 апреля 2011

ваш оператор> = - это функция-член совершенно другого типа, не связанная с Point, если речь идет о компиляторе.Я думаю, что вы хотите сделать:

template< T >
bool operator >= ( T const& a, T const& b ) {... }

забыть класс и просто сделать его глобальной функцией.И вам не понадобится явная реализация шаблона.Фактически, я видел только один раз, когда вы использовали шаблонный класс, объявленный внутри библиотеки и использованный в другом проекте, чего вы явно здесь не делаете.

...