Brooks Xi
Brooks Xi

Reputation: 33

My explicit instantiation of template class seems doesn't work

I wrote a short program to test the template class's explicit instantiation as follows:

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

I know if I inherit Point from less_than_comparable, the code will pass the compiling. But my question is why it doesn't work if I use explicit instantiation? I use G++ 4.4.5 running on Ubuntu 10.04. Any comments will be appreciated. Thanks.

Upvotes: 3

Views: 1593

Answers (4)

Vitus
Vitus

Reputation: 11922

The problem is that friend functions defined inside class-like types are not injected into enclosing namespace.

The principle you are refering to is called "friend name injection", but this has been replaced in current C++ standard by "ADL" (Argument Dependent Lookup, also called Koenig Lookup). ADL examines all namespaces associated with function parameter types for matching function.

In your case, when you call operator>= in p1 >= p2 (i.e. operator>=(p1, p2);). ADL looks for matching function in the namespace of Point, but Point doesn't have such function.

If you inherit Point from less_than_comparable, operator>= becomes part of namespace of Point and ADL can find it here.

You can check, that no friend name injection takes place here.

Upvotes: 2

Tony Delroy
Tony Delroy

Reputation: 106096

Explicit instantiation is simply a way to force the compiler to compile a particular template within that translation unit - it has no affect on the lookup of names.

To get what you appear to want, you could for example:

class Point : public less_than_comparable<Point> {

Upvotes: 1

iammilind
iammilind

Reputation: 69988

The code doesn't work because Point is not a template class where you have defined operator >=. If you want to compile this code then define operator >= in Point class as well. Note that p1 and p2 are no where related to less_than_comparable.

As side note, why you have defined operator for "greater than equal to" operator in the name of less_than_comparable ?

Upvotes: 1

DXM
DXM

Reputation: 4543

your operator >= is a member function of a completely different type that is unrelated to Point as far as the compiler is concerned. I think what you want to do is:

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

forget the class and just make it a global function. And you won't need explicit template instantiation. In fact the only time I've seen it used was when you had template class declared inside a library and used in another project, which you are obviously not doing here.

Upvotes: 0

Related Questions