今天早晨,我看着C++ Templates: The Complete Guide (2nd Edition) / official site(总体来说很好)看到了一个我不太理解的部分(如果有这本书,则是12.5.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);
^
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)。无论哪种情况,都不能证明作者陈述的规则,这是第二个引用同一类中较早版本的规则。
答案 0 :(得分:2)
这本书是对的。 [temp.friend]p1-突出显示相关部分:
对于不是模板声明的朋友函数声明:
如果朋友的名字是合格的或不合格的 template-id ,[...]
如果朋友的名字是 qualified-id ,并且在指定的类或名称空间中找到了匹配的非模板函数,则[...]
< / li>如果朋友的名字是 qualified-id 并且在指定的类或名称空间中找到了匹配的函数模板,则Friend声明将引用推导的专业化该功能模板
[...]