Here is two-phase name lookup for template from iso-standard:
When looking for the declaration of a name used in a template definition, the usual lookup rules (6.4.1, 6.4.2) are used for non-dependent names.
The lookup of names dependent on the template parameters is postponed until the actual template argument is known
Sample codes:
#include <iostream>
void WithoutTemplate(int) {std::cout << "NonTemplate: int\n";}
template<typename T>
void WithTemplate(T) {std::cout << "no match\n";}
template<>
void WithTemplate(int) {std::cout <<"Template: int\n";}
template<typename T>
void test(T)
{
WithTemplate(1.1);
WithoutTemplate(1.1);
}
void WithoutTemplate(double) {std::cout << "nontemplate: double\n";}
template<>
void WithTemplate(double) {std::cout << "template: double\n";}
int main()
{
test(1.1);
}
output:
template: double NonTemplate: int
There are two functions: WithTemplate
and WithoutTemplate
. The parameter 1.1
is non-dependent(though it is prvalue, which has no name? I assume it still obey non-dependent name's rules)
- name lookup of
WithoutTemplate
meets 2-phase lookup, because when callingWithoutTemplate(1.1)
,void WithoutTemplate(double)
is not visible. So the outputNonTemplate: int
is easy to understand. - However, the case which invokes full specialization function quite confuses me. its behaviour is opposite to the standard's rules(2-phase lookup). I thought it should output
template: int
So, is there other name lookup rules for specialization? Or something else I misunderstand?
Here is what I have read:
std::cout
which is fully qualified. (1.1 isn't a name.) – Alan StokesWithoutTemplate
uses 2-phase name lookup here which also uses non-dependent name. SoWithTemplate
may also use it, but I'm not sure, so the question isstragety...
– Chen Litest
are non-dependent, so the normal rules apply. At the point where you callWithoutTemplate
only one definition is visible, so that's the one that is called. (If you were to replace1.1
with(T) 1.1
you might see different results.) – Alan Stokes