Reputation: 33
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
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
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
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
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