依赖模板的名称解析应该找不到没有链接的声明吗?

时间:2018-07-22 12:47:24

标签: c++ templates language-lawyer linkage name-lookup

在c ++标准[temp.point]中,其写为​​:

  

表达式的实例上下文,取决于   模板参数是具有外部链接的声明的   在模板实例化点之前声明   在同一个翻译部门进行专业化。

然后在[临时候选人]:

  

对于使用关联名称空间的部分查找   ([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 ??

此代码实际上可以编译,那么此标准段是什么意思?

1 个答案:

答案 0 :(得分:8)

这是标准中的缺陷。最初在core issue 561中提到,委员会对此进行了判断

  

2006年4月会议上的笔记:

     

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

不幸的是,相应的修补程序不足,如core issue 1258所述:

  

C ++ 11扩展了相关函数调用的查找规则(17.7.4.2 [temp.dep.candidate]第1条第2项),以包括具有内部链接的函数;以前只考虑具有外部链接的功能。但是,17.7.4.1 [温度点]第6段仍然说,

     
    

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

  
     

大概这个措辞被忽略了,应该与新规范保持一致。

也就是说,第二个引用段落的前面的措辞是

  

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

..已针对C ++ 11进行了修改,但是该更改错过了您的第一个引用,因此变得毫无意义。目的是不区分具有内部链接的功能。