Template specialization doesn't see a function in its point of instantiation

拜拜、爱过 提交于 2020-01-03 16:52:31

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!