【问题标题】:What are the rules for using qualified names in friend declarations?在朋友声明中使用限定名的规则是什么?
【发布时间】:2023-03-25 23:06:01
【问题描述】:

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

namespace a {

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

}

错误是:

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

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

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

【问题讨论】:

    标签: c++ namespaces friend


    【解决方案1】:

    您要查找的段落是 [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) 这意味着类或函数的名称是不合格的。

    【讨论】:

      猜你喜欢
      • 2019-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多