I have written this code to understand template name lookup:
//void bar(int);
template <typename T>
void foo(T x)
{
bar(x);
}
void bar(int x)
{
std::cout << "bar(int)\n";
}
template <int>
void foo(int i)
{
bar(i);
}
int main()
{
foo<int>(4);
std::cout << "\ndone!\n";
}
I've commented out the declaration of function bar(int) intentionally. This function bar(int) is used as a dependent name in the template function foo. So it is bound upon instantiation.
- I've defined
barright afterfooand before a specialization offoo<int>so that this latter can seebar(int).
But when I compile the code I get this error:
‘bar’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]|. And if I un-comment the declaration of bar(int) it works fine?!
If I must declare a name before using it in a template as a dependent-name then why C++ allows that if not instantiated. (the code works if I don't "use" templated function
foo)?template <typename U> void do_it(U u) { print(u); // not bound until instantiation }
So what is the idea behind allowing calling print(u) in do_it which was not already declared and will fail upon instantiation?
In your program, this definition:
does not actually define a specialization of the
fooprimary template. So when you make this call:you end up calling the primary template. Lookup for the name
bardoesn't find that name, and you get an error.If instead, you actually write a specialization of
fooforintlike this:then the call
foo<int>(4);is fine, because it calls the specialization, and lookup forbarat that point does find that name.Now going back to your program (without the specialization), what happens if
foois never instantiated, because there's no call, for example? Well, the program is still wrong, but the compiler may not tell you about it. This is the behavior that you are describing withprintanddo_it, and this is formally known as ill-formed, no diagnostic required.