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

时间:2015-01-15 22:54:21

标签: c++ namespaces friend

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

namespace a {

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

}

错误是:

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

如果我们从声明中删除::,根据标准,foo将被引入名称空间a(尽管它不可​​见)。 <{1}}中预先指定foo不是必需的。

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

1 个答案:

答案 0 :(得分:2)

您正在寻找的段落是[dcl.meaning](C ++ 11中的8.3(1)):

  

(...) declarator-id 除了其类之外的成员函数或静态数据成员的定义,函数或变量的定义或显式实例化之外,不应限定命名空间之外的命名空间,或其命名空间之外的显式特化的定义,或者是另一个类或命名空间的成员的友元函数的声明。 declarator-id 被限定时,声明应引用先前声明的限定符所引用的类或命名空间的成员(或者,在命名空间的情况下) ,该命名空间的内联命名空间集合的元素。)

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

namespace a { }

void a::foo() { }

除非已在命名空间内使用非限定声明符声明a::foo。因为朋友也不例外,你也不能为朋友这样做。

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

  

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

     

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