Consider the following testcase, where the call to foo(B&) should be resolved at template instantiaton time of the function template g. struct A {}; struct B {}; void foo(A&); template <class T> void g(T& t) { foo(t); } void foo(B&); void bar(B& b) { g(b); } This works correctly. Now add some namespace blurb (which shouldn't really change anything here) and get namespace X { struct A {}; struct B {}; } void foo(X::A&); template <class T> void g(T& t) { foo(t); } void foo(X::B&); void bar(X::B& b) { g(b); } where 4.1 now rejects this with t2.C: In function ‘void g(T&) [with T = X::B]’: t2.C:18: instantiated from here t2.C:11: error: invalid initialization of reference of type ‘X::A&’ from expression of type ‘X::B’ t2.C:6: error: in passing argument 1 of ‘void foo(X::A&)’ even more funny, adding an unrelated overload of foo: namespace X { struct A {}; struct B {}; struct C {}; } void foo(X::A&); void foo(X::C&); template <class T> void g(T& t) { foo(t); } void foo(X::B&); void bar(X::B& b) { g(b); } we reject it with t3.C: In function ‘void g(T&) [with T = X::B]’: t3.C:20: instantiated from here t3.C:13: error: no matching function for call to ‘foo(X::B&)’ t3.C:7: note: candidates are: void foo(X::A&) t3.C:8: note: void foo(X::C&) EDG rejects the latter two with a consistent error message (in -strict_ansi mode): t3.C(13): error: no instance of overloaded function "foo" matches the argument list argument types are: (X::B) foo(t); ^ detected during instantiation of "void g(T &) [with T=X::B]" compilation aborted for t3.C (code 2) g++ accepts even the following, which may hint at the reason for the inconsistent error messages? namespace X { struct B {}; } template <class T> void g(T& t) { foo(t); } void foo(X::B&); void bar(X::B& b) { g(b); } I'm really unsure who's at fault here and if this is rejects-valid or rejects-invalid. Digging in the standard now, but maybe someone can point me at the relevant section.
It looks like we are looking up the name 'foo' from bar in X only (because X::B is a qualified type and so special name-lookup rules apply), but search the scope of bar (or g) only from the context of g. So the following compiles: namespace X { struct A {}; struct B {}; } void foo(X::A&); template <class T> void g(T& t) { foo(t); } namespace X { void foo(X::B&); } void bar(X::B& b) { g(b); }
From 14.6.2/1 one could argue that foo is a dependent name and thus is looked up in the context of the point of instantiation, bar, which should find foo(X::B&). But 14.6.4/1 contradicts this in telling we search the visible decls from the point of the template definition and only those from namespaces associated with the types of the function arguments from the instantiation context and the definition context. Which would make the last, working, example a accepts-invalid.
There are a couple of DR reports about this issue. Basicially what you are doing is invalid (IIRC). The error message which EDG is less helpful than the error message GCC gives because it does not list the overloaded set while GCC does. That is the only difference.
(In reply to comment #2) > Which would make the last, working, example a accepts-invalid. You missed Argument dependent namelookup rules (Koenig) which is 3.4.2.
Anyways the revelevent bug reports about why the second and thrid examples are invalid code are PR 5660 and PR 2922.
This is invalid. The last example has argument-dependent lookup working which is still required to run even after finding an overloaded set. PR 2922 explains all this correctly (and so does the change log for the patch): * semantics.c (perform_koenig_lookup): For dependent calls, just return the set of functions we've found so far. Later, it will be augmented by those found through argument-dependent lookup. * name-lookup.c (lookup_arg_dependent): Implement DR 164 by removing the optimization that skips namespaces where the functions were originally found.
by 14.6.2/1 I would expect search from both instantiation and definition. by 14.6.4/1 I would expect (as is the case for 4.1) search from the instantiation point to be restricted to namespace X. I do not see how Koenig lookup can make it /fail/, but only work (and that it doesn't). We're still speaking about namespace X { struct A {}; struct B {}; } void foo(X::A&); template <class T> void g(T& t) { foo(t); } void foo(X::B&); void bar(X::B& b) { g(b); }
Please someone else comment on this.
(In reply to comment #7) > by 14.6.2/1 I would expect search from both instantiation and definition. > by 14.6.4/1 I would expect (as is the case for 4.1) search from the > instantiation > point to be restricted to namespace X. > I do not see how Koenig lookup can make it /fail/, but only work (and that it > doesn't). Koenig lookup does not apply here as foo is not in the namespace X.
> We're still speaking about > > namespace X { > struct A {}; > struct B {}; > } > > void foo(X::A&); > > template <class T> > void g(T& t) > { > foo(t); > } > > void foo(X::B&); > > void bar(X::B& b) > { > g(b); > } This is invalid as Koenig look cannot and will not find the second foo as it is not in the namespace X. The overloaded set for foo in g only contains the first foo and then when instantiating it, it reruns the Koenig rules and that says it can only find foo in the namespace X so the code is rejected. So this is a dup of bug 2922 after all. *** This bug has been marked as a duplicate of 2922 ***