Name resolution of functions inside templates instantiated with qualified types
c++, name-lookup, namespaces, overloading, templates
Solution
I think the rule is 14.6.4.2p1:
For a function call that depends on a template parameter, the candidate functions are found using the usual lookup rules (3.4.1, 3.4.2, 3.4.3) except that:
— For the part of the lookup using unqualified name lookup (3.4.1) or qualified name lookup (3.4.3), only function declarations from the template definition context are found.
— For the part of the lookup using associated namespaces (3.4.2), only function declarations found in either the template definition context or the template instantiation context are found.
`void foo(n::A) {}` is not visible in the template definition context because it comes after and `foo` is not in the same namespace as `n::A`. So it needs to be either visible before the template definition or included in the same namespace like below:
namespace n
{
void foo(n::A) {}
}
Problem
Consider the following C++ code example: ``` namespace n { struct A {}; } struct B {}; void foo(int) {} template<typename T> void quux() { foo(T()); } void foo(n::A) {} void foo(B) {} int main() { quux<n::A>(); // Error (but works if you comment out the foo(int) declaration) quux<B>(); // Works return 0; } ``` As indicated in the comment, the template instantiation `quux<n::A>()` causes a compiler error (on GCC 4.6.3): ``` foo.cpp: In function ‘void quux() [with T = n::A]’: foo.cpp:22:16: instantiated from here foo.cpp:13:5: error: cannot convert ‘n::A’ to ‘int’ for argument ‘1’ to ‘void foo(int)’ ``` Can someone explain to me what is going on? I would have expected for it to work the same as with `quux<B>()`. It must have something to do with when `foo` is considered dependent. Unfortunately my C++ foo is not good enough. The example compiles fine, when the `foo(int)` declaration is not present, which is also surprising to me. Any hints, explanations and workarounds are welcome. Update 1: I do not want to (read cannot) move the declaration of `foo(n::A)` before the definition of `quux` (which would avoid the error). Update 2: Thanks for David for pointing out the related question Template function call confused by function with wrong signature declared before template. The accepted answer by Johannes Schaub - litb proposes a wrapper class solution, that would also work in my case as a workaround. However, I'm not 100% happy with it. Update 3: I solved the issue by putting the definition of `foo(n::A)` in namespace `n`. Thanks for the helpful answers of Jesse Good and bames53 that not only point out the relevant sections of the standard, but also provide alternative solutions. Thanks to David Rodríguez - dribeas for his explanation when I did not understand the proposed solutions properly and all other contributors.