Hi Stephan,
Stephan Bergmann schrieb:
If I understand things correctly, the above problem boils down to
struct A {};
struct B {};
void f(A*);
template<typename T> void g(T t) { f(t); } // line 4
void f(B*);
void h(B*b) { g(b); } // line 6
being rejected by GCC 4.1, on the grounds that f(B*) is not visible at
the point of definition of template g.
No. The problem is slightly different. The above code is OK.
The following more closely matches the problem:
namespace NS
{
struct A {};
struct B {};
}
void f(A *);
namespace NS { ff(A *); }
template<typename T> void g(T t)
{
f(t); // unqualified lookup - this fails
ff(t); // argument-dependent lookup - this successds
::f(t); // qualified id - ??
}
void f(B*);
namespace NS { ff(B *); }
void h(B*b) { g(b); } // line 6
After a quick look into Vandevoorde/Josuttis (which is often easier than
The Standard...), my understanding is that f in line 4 is an unqualified
dependent name (its argument type is dependent), and so two-phase lookup
happens for f, first in line 4 (seeing only f(A*)), and then in line 6
at the point of instantiation of g for B (seeing also f(B*)).
According to clause 14.6.4.2 of the standard that two-phase lookup works
differently than your simplified paraphrase suggests:
- the ordinary unqualified lookup considers only the definition context
- argument-dependent lookup considers both definition and instantiation
contexts
In the example you gave above, the global namespace is searched again by
argument-dependent lookup, so ::f(B*) is found in phase two. But in my
case (and the UNO one) the argument dependent lookup only finds
declarations in namespace NS..
Note: In the UNO case the template lives in a namespace itself, which
may or may not be identical to the namespace (NS). But that doesn't
change anything, because this only affects the unqualified lookup.
And of course the declarations of struct A and f(A*) is mere scaffolding
in the example. Without them, the error still occurs only at the point
of instantiation (but then there are no candidates functions for f).
Actually the most hideous case is when A is a public base class of B,
because in that case the instantiation of g<B> succeeds, but should call
f(A*) instead of f(B*).
BTW, I'm not entirely sure how the *qualified* lookup case (the ::f(t)
call in the template definition) would behave. I have only the original
standard at hand and here 14.6.2/1 and 14.6.4/1 seem to disagree.
Of course all this becomes a real problem, because most C++ compilers
never got this right (and g++ is only getting there recently).
Ciao, Joerg
--
Joerg Barfurth Sun Microsystems - Desktop - Hamburg
>>>>>>>>>>>>>>>>>> using std::disclaimer <<<<<<<<<<<<<<<<<<<<<<<
Software Engineer [EMAIL PROTECTED]
OpenOffice.org Configuration http://util.openoffice.org
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]