在好友声明中使用限定名称的规则是什么?

What are the rules for using qualified names in friend declarations?

本文关键字:定名称 规则 是什么 好友 声明      更新时间:2023-10-16

以下代码产生编译错误(至少在最新版本的 gcc 上):

namespace a {
class X { friend void ::foo(); };
}

错误是:

'void foo()' should have been declared inside '::'

如果我们从声明中删除::,根据标准,foo将被引入命名空间a(尽管它不可见)。不需要在a内部预先声明 foo。

我的问题是,鉴于上述情况,为什么在全局命名空间中预先声明是一项要求?为什么名称foo不成为全局命名空间的成员?我在标准中也找不到任何明确禁止的段落,所以我很想知道。

您要

查找的段落是[dcl.meaning](C++11中的8.3(1)):

(...声明符 id 不得限定,除非定义其类之外的成员函数或静态数据成员,在其命名空间之外定义或显式实例化命名空间的函数或变量,或定义其命名空间之外的显式专用化,或者声明作为另一个类或命名空间成员的友元函数。声明符 id 是限定的时,声明应引用限定符所引用的类或命名空间的先前声明的成员(或者,如果是命名空间,则引用该命名空间的内联命名空间集的元素)。

(强调我的)这意味着你不能写

namespace a { }
void a::foo() { }

除非已在命名空间中使用非限定声明符声明a::foo。而且由于朋友没有例外,您也不能为朋友这样做。

[namespace.memdef](C++11)中的7.3.1.2(3))中的脚注更明确地提到了朋友的特殊情况:

(...如果非本地类中的友元声明首先声明一个类或函数95,则友元类或函数是最内层封闭命名空间的成员。(...)

95)这意味着类或函数的名称是不限定的。