代码之家  ›  专栏  ›  技术社区  ›  Oliv

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

  •  7
  • Oliv  · 技术社区  · 6 年前

    在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 回复  |  直到 6 年前
        1
  •  8
  •   Columbo    6 年前

    这是标准中的一个缺陷。最初地址在 core issue 561 如果委员会认为

    2006年4月会议的说明:

    小组一致认为 内部链接函数应该通过查找找到(尽管如果通过重载解决方案选择它们可能会导致错误)。

    不幸的是,相应的修复方法不充分,如 core issue 1258 :

    C++ 11扩展了相关函数调用的查找规则(177.4.2[TEMP.DeP.Advi],第1段子弹2),以包含具有内部链接的函数;以前只考虑了具有外部链接的函数。然而,17.7.4.1[温度点]第6段仍然指出,

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

    大概这个措词被忽略了,应该与新的规范相协调。

    也就是说,你引用的第二段的前一句话是

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

    …它被修改为C++ 11,但是这个变化错过了你的第一句话,使它毫无意义。其目的是不区分具有内部链接的功能。