Reputation: 63
Consider the following code:
#include <iostream>
template<typename T>
void f(T t)
{
(void)t;
std::cout << "templated f(T)\n";
}
template<typename T>
void entry(T t)
{
f(t);
}
void f(double d)
{
(void)d;
std::cout << "normal f(double)\n";
}
int main()
{
double d = 0.0;
entry(d);
return 0;
}
Output:
templated f(T)
I find this surprising, because I thought that the plain function will be selected over any templated version. Why does this happen?
Another thing I noticed while playing around is that: if I put the normal function void f(double)
before the templated void entry(T)
function the code will call the normal function, basically outputting:
normal f(double)
Therefore my other question: why does the order matter in this particular example?
Upvotes: 6
Views: 92
Reputation: 119582
f
is a dependent name, since it depends on t
whose type is a template parameter. The name lookup rules for dependent names are given in [temp.dep.res]/1:
In resolving dependent names, names from the following sources are considered:
- Declarations that are visible at the point of definition of the template.
- Declarations from namespaces associated with the types of the function arguments both from the instantiation context (14.6.4.1) and from the definition context.
In other words, normally name lookup inside a template only finds names that have been declared before the template definition (which is not that surprising, since it's the same as for non-templates). The second bullet point allows names declared after the template definition to be found, but only when ADL occurs. This won't be the case when the argument is a fundamental type such as double
.
Upvotes: 7
Reputation: 11768
The overload for f(double)
is not visible to the compiler when the entry(T)
template is parsed. Therefore, it won't participate in overload resolution when the entry(T)
template is instantiated. This is just an obscure rule when it comes to resolving overloads in a template instantiation context. In order for an overload to be considered, it has to already have been visible in the translation unit before the template definition was parsed.
Upvotes: 0