Re: template parameter's namespace exposed?
Matjaz Depolli wrote:
I've got a problem that I will try to demonstrate with the following
code:
namespace N {
class A {
};
template<class T1, class T2>
T1 operator+ (T1 op1, T2 op2) {return op1;}
}
template<class T>
class B {
};
int main() {
N::A a1, a2;
a1 + a2; // works as it should
B<N::A> b1, b2;
b1 + b2; // oops, this one compiles too!
B<int> b3, b4;
b3 + b4; // no match for operator +, just the way it should be
}
The unwanted behaviour here is, that templated operator inside the
namespace makes itself visible to the templated classes outside that
namespace, instantiated with a member of the same namespace as their
template parameter. It is not like B extends N::A, in which case this
would be ok.
I find this problem quite surprising and I'm wandering whether this is
a gcc bug (I'm using gcc version 3.4.4 -mingw special) or is this the
way the standard says it should be. If the latter is the case than I
have just found out the hard way that fully templated operators are too
great of a beast to let loose - even in a well hidden namespaces :)
Finding the overloaded addition operator in the N namespace when adding
b1 and b2 is not a bug in the compiler. Instead this code demonstrates
"argument dependent lookup" (ADL). The addition operator is found in
the N namespace because the parameterized type of the template class
arguments being summed is defined in that namespace. Essentially, the
compiler is allowed to search any namespace in the least way associated
with the arguments of a function call when searching for the function
to match the call.
The problem here is not so much ADL itself (without which overloaded
operators defined within a namespace would not be very useful at all) -
but rather the problem is defining an unrestricted overloaded operator
in the first place. The overloaded plus operator is simply too
permissive. After all, the types of the two arguments can be completely
unrelated (!). So the solution would be to narrow the specification of
the overloaded plus operator and have it state more precisely the types
of its parameters. For example:
A operator+(const A& lhs, const A& rhs)
{
...
}
or
template <class T>
B<T> operator+(const B<T>& lhs, const B<T>& rhs)
{
...
}
for adding two template class objects together.
Greg
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]