3

我编写了一个简短的程序来测试模板类的显式实例化,如下所示:

#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’
}

我知道如果我从 less_than_comparable 继承 Point,代码将通过编译。 但我的问题是,如果我使用显式实例化,为什么它不起作用? 我使用在 Ubuntu 10.04 上运行的 G++ 4.4.5。任何意见将不胜感激。谢谢。

4

4 回答 4

2

问题是在类类类型中定义的友元函数没有注入到封闭的命名空间中。

您所指的原理称为“朋友名称注入”,但在当前的 C++ 标准中已被“ADL”(Argument Dependent Lookup,也称为Koenig Lookup)取代。ADL 检查与函数参数类型关联的所有命名空间以查找匹配函数。

在你的情况下,当你打电话operator>=p1 >= p2(即operator>=(p1, p2);)。ADL 在 的命名空间中寻找匹配的函数Point,但Point没有这样的函数。

如果您继承Pointless_than_comparableoperator>=则成为命名空间的一部分,PointADL 可以在此处找到它。

你可以检查一下,这里没有朋友名字注入。

于 2011-04-25T10:38:29.357 回答
1

该代码不起作用,因为Point它不是您定义的模板类operator >=。如果要编译此代码,请operator >=在 Point 类中定义。请注意p1和 与p2没有任何关系less_than_comparable

作为旁注,为什么您以 的名义为“大于等于”运算符定义运算符less_than_comparable

于 2011-04-25T08:26:54.533 回答
1

显式实例化只是一种强制编译器在该翻译单元中编译特定模板的方法——它对名称的查找没有影响。

为了得到你想要的,你可以例如:

class Point : public less_than_comparable<Point> {
于 2011-04-25T08:36:33.130 回答
0

您的运算符 >= 是完全不同类型的成员函数,就编译器而言,它与 Point 无关。我想你想做的是:

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

忘记这个类,让它成为一个全局函数。而且您不需要显式模板实例化。事实上,我唯一一次看到它使用的是当您在库中声明模板类并在另一个项目中使用时,您显然在这里没有这样做。

于 2011-04-25T08:26:32.467 回答