模板相关的名称解析不应该找到没有链接的声明?

Oli*_*liv 7 c++ templates linkage language-lawyer name-lookup

在c ++标准[temp.point]中写道:

依赖于模板参数的表达式的实例化上下文是 在同一翻译单元中模板特化的实例化之前声明的具有外部链接的声明.

然后在[temp.dep.candidate]中:

对于使用关联命名空间([basic.lookup.argdep])查找的部分,仅找到在模板定义上下文或模板实例化上下文中找到的函数声明.

这是否意味着以下代码应该失败:

namespace A{
    struct S{};
}

template<class T>
void g(T a){
    f(a); //f will be found by argument dependent lookup
}

namespace A{
    static void f(S); //but f doesn't have external linkage
}

void test(A::S i){
    g(i);
}
//point of instantiation of g
//A::f(S) doesn't have external linkage 
//=> so it's not in the instantiation context of template g ??
Run Code Online (Sandbox Code Playgroud)

这段代码实际编译,那么这个标准段落意味着什么?

Col*_*mbo 8

这是标准中的缺陷.最初在核心问题561中提到,委员会在那里判断

2006年4月会议记录:

该小组的共识是[..] 内部链接函数应该通过查找找到(尽管如果通过重载决策选择它们可能会导致错误).

不幸的是,相应的修复是不够的,正如核心问题1258中所阐述的那样:

C++ 11扩展了依赖函数调用的查找规则(17.7.4.2 [temp.dep.candidate]第1段子弹2),以包含具有内部链接的函数; 之前只考虑了具有外部联系的功能.但是,17.7.4.1 [temp.point]第6段仍然说,

依赖于模板参数的表达式的实例化上下文是在同一翻译单元中模板特化的实例化之前声明的具有外部链接的声明集.

据推测,这个措辞被忽略了,应该与新规范协调一致.

也就是说,你的第二段引用的先前措辞是

对于使用关联命名空间(3.4.2)的查找部分,仅找到在模板定义上下文或模板实例化上下文中找到的具有外部链接的函数声明.

..这是针对C++ 11修改的,但是这个改变错过了你的第一个引用,使它变得毫无意义.目的是不区分具有内部联系的功能.