我不明白为什么不正确
#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(){}
在模板函数 fnc
中调用 f(t)
取决于模板参数,然后名称查找必须位于实例化点 . 我看到标准(C 14)14.6.4.1/1
对于函数模板特化,成员函数模板特化,或成员函数或类模板的静态数据成员的特化,如果特化是隐式实例化的,因为它是从另一个模板特化和其中的上下文中引用的引用取决于模板参数,专门化的实例化点是封闭专门化的实例化点 . 否则,这种特化的实例化点紧跟在引用特化的命名空间范围声明或定义之后 .
f(CL)
在 fnc<CL>
实例化时可见,但所有编译器(VS,gcc,clang)都会出错 . 这种行为的原因是什么?
1 回答
这里
fnc
的参数t
是一个从属名称,在解析模板时无法解析 . 相反,它们在实例化时再次被查找 . 这就是所谓的两阶段查找:第一阶段是解析模板,第二阶段是实例化 .您的问题的答案在于,在POI(实例化点)执行的第二次查找仅为 ADL . 由于struct
CL
未在void f(CL)
的同一名称空间内定义,因此POI查找不会发生,也不会找到它 .如果您尝试将struct
CL
的定义放入命名空间以使ADL生效,它将很好地编译 .根据unqualified name lookup的规则,(由我粗体)