合格的朋友功能模板实例化

时间:2019-01-05 19:39:31

标签: c++ templates language-lawyer c++17

今天早晨,我看着C++ Templates: The Complete Guide (2nd Edition) / official site(总体来说很好)看到了一个我不太理解的部分(如果有这本书,则是12.5.2)。忽略这里无关紧要的内容:

  

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

     
      
  1. 如果名称不正确[...]

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

  4.   

使用以下代码

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);
                               ^

c语错误:

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

我试图弄清这件事的深处,并且我已经重新输入了几次代码(尽管有人读过这本书,但是还是要重新输入)。规则正确,编译器错误吗?代码不是该规则的正确证明吗?

完整的代码包括一个较早的朋友函数定义:

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

哪个clang接受而gcc拒绝(即different question)。无论哪种情况,都不能证明作者陈述的规则,这是第二个引用同一类中较早版本的规则。

1 个答案:

答案 0 :(得分:2)

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

  

对于不是模板声明的朋友函数声明:

     
      
  • 如果朋友的名字是合格的或不合格的 template-id ,[...]

  •   
  • 如果朋友的名字是 qualified-id ,并且在指定的类或名称空间中找到了匹配的非模板函数,则[...]

    < / li>   
  • 如果朋友的名字是 qualified-id 并且在指定的类或名称空间中找到了匹配的函数模板,则Friend声明将引用推导的专业化该功能模板

  •   
  • [...]

  •