1

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 calling WithoutTemplate(1.1), void WithoutTemplate(double) is not visible. So the output NonTemplate: 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:

Chen Li
  • 4,824
  • 3
  • 28
  • 55
  • 1
    Two-phase name lookup isn't relevant here; your template definition doesn't use any dependent names - the only name you use is `std::cout` which is fully qualified. (1.1 isn't a name.) – Alan Stokes Dec 08 '17 at 16:42
  • @AlanStokes I think `WithoutTemplate` uses 2-phase name lookup here which also uses non-dependent name. So `WithTemplate ` may also use it, but I'm not sure, so the question is `stragety...` – Chen Li Dec 08 '17 at 16:47
  • The names looked up within `test` are non-dependent, so the normal rules apply. At the point where you call `WithoutTemplate` only one definition is visible, so that's the one that is called. (If you were to replace `1.1` with `(T) 1.1` you might see different results.) – Alan Stokes Dec 08 '17 at 16:53

1 Answers1

4

Your program has undefined behaviour, because you define the explicit specialization of WithTemplate<double> after it has been implicitly instantiated through the call WithTemplate(1.1). Explicit specializations must appear before any use of them that would cause instantiation - see e.g. http://en.cppreference.com/w/cpp/language/template_specialization.

So there's no point trying to reconcile the behaviour with what the standard says; the standard explicitly says nothing about what should happen here.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64