代码之家  ›  专栏  ›  技术社区  ›  Ryan Haining

合格朋友功能模板实例化

  •  -1
  • Ryan Haining  · 技术社区  · 7 年前

    看着 C++ Templates: The Complete Guide (2nd Edition) / official site (总体来说很好)今天早上我遇到了一个我无法理解的部分(12.5.2如果你有这本书的话)。省略这里看起来不相关的内容:

    如果[在友元声明中]的名称后面没有尖括号,则有两种可能

    1. 如果名称不合格[…]

    2. 如果名字 是 合格(包含 :: )名称必须引用以前声明的函数或函数模板。匹配函数优先于匹配函数模板。但是,这样的友元声明不能是定义。

    使用以下代码

    void multiply(void*);
    
    template <typename T>
    void multiply(T);
    
    class Comrades {
        // ... skipping some friends that do not effect the error message
        friend void ::multiply(int); // refers to an instance of the template
        // ...
    };
    

    GCC错误:

    error: ‘void multiply(int)’ should have been declared inside ‘::’
         friend void ::multiply(int);
                                   ^
    

    铿锵误差:

    error: out-of-line declaration of 'multiply' does not match any
      declaration in the global namespace
    friend void ::multiply(int);
                  ^~~~~~~~
    

    我正试图弄清这一点,我已经重新输入了几次代码(不过,如果有人有这本书的话……)。规则正确吗?编译程序错误吗?代码不是规则的正确演示吗?

    完整的代码包括一个早期的friend函数定义:

    class Comrades {
        friend void multiply(int) { }
        friend void ::multiply(int);
    }
    

    Clang接受并且GCC拒绝(这是 different question )无论哪种情况,它都不能证明作者所说的规则,而是引用同一类中较早的规则的第二个规则。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Rakete1111    7 年前

    这本书是对的。 [temp.friend]p1 -突出显示相关部分:

    对于非模板声明的友元函数声明:

    • 如果朋友的名字是合格或不合格的 模板ID ,[…]

    • 如果朋友的名字是 合格身份证 在指定的类或命名空间中找到匹配的非模板函数,[…]

    • 如果朋友的名字是 合格身份证 在指定的类或命名空间中找到匹配的函数模板,friend声明引用该函数模板的派生专门化。

    • […]