问题
I don't understand why it isn't correct
#include <iostream>
using namespace std;
struct CL{};
template <typename T>
void fnc(T t)
{
f(t);
}
namespace NS {
void f(CL){}
void fn() {fnc(CL()); /*error is here*/}
//point of instantiation fnc<CL> is here (in namespace scope,
//according to 14.6.4.1/1)
}
int main(){}
Calling f(t)
in template function fnc
is dependent on template parameter and then name lookup must be at an instantiation point. I saw Standard (C++ 14) 14.6.4.1/1
For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization. Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.
f(CL)
is visible at a point of instantiation of fnc<CL>
, but all the compilers (VS, gcc, clang) give an error. What is reason for that behavior?
回答1:
Here the argument t
of fnc
is a dependent name, which cannot be resolved when parsing templates. Instead, they are looked up again at the point of instantiation. This is so-called two-phase lookup: the 1st phase is the parsing of a template, and the 2nd phase is its instantiation.
The answer to your question lies in the fact that the 2nd lookup performed at the POI (point of instantiation) is only an ADL. Because the struct CL
is not defined inside the same namespace with void f(CL)
, the POI lookup would therefore not take place and would not find it.
If you try to put the definition of the struct CL
into the namespace to make ADL take effect, it will compile well.
namespace NS {
struct CL{};
void f(CL){}
//...
}
According to the rule of unqualified name lookup, (bold by me)
For a dependent name used in a template definition, the lookup is postponed until the template arguments are known, at which time ADL examines function declarations with external linkage (until C++11) that are visible from the template definition context as well as in the template instantiation context, while non-ADL lookup only examines function declarations with external linkage (until C++11) that are visible from the template definition context (in other words, adding a new function declaration after template definition does not make it visible except via ADL).
来源:https://stackoverflow.com/questions/33434606/template-specialization-doesnt-see-a-function-in-its-point-of-instantiation