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.