Here is some C++ code:
namespace A {
int f(int x) { return 0; }
int f(long x) { return 1; }
template<class T> int g(T x) {
return f(x);
}
}
namespace B {
struct C {};
}
namespace A {
int f(B::C x) { return 2; }
}
void h() {
A::g(B::C());
}
In namespace A, the code declares a few overloads of a function f, and a templated function g which calls f. Then we declare a new type in namespace B and overload f for the new type in namespace A. Compiling with g++ 4.2 gives
order.cpp: In function ‘int A::g(T) [with T = B::C]’:
order.cpp:21: instantiated from here
order.cpp:7: error: no matching function for call to ‘f(B::C&)’
order.cpp:3: note: candidates are: int A::f(int)
order.cpp:4: note: int A::f(long int)
The code works if I do any of the following:
- Remove the namespaces.
- Move the overload of f for B::C into namespace B (thanks to Koenig lookup).
- Move the declaration of B::C and its f overload above the definition of g().
I’m particularly puzzled by (3), since I was under the impression that overload resolution should be independent of the order of declarations. Is this expected C++ behavior?
Clang gives the following error message, which gives some clues to the problem:
Specifically, you’ve run into a detail of two-phase lookup of dependent names in template definitions. In C++98, [temp.dep.candidate] says:
Since
A::f(B::C x)isn’t found using associated namespaces (i.e. argument-dependent lookup), it has to be visible at the template definition site, not just at the point of instantiation.