【问题标题】:VS2015 and clang compile this code, but g++ rejects it. Which one is correct?VS2015 和 clang 编译此代码,但 g++ 拒绝它。哪一个是正确的?
【发布时间】:2017-06-05 18:55:09
【问题描述】:

VS2015clang 编译这段代码,但 g++ rejects it.

namespace A {
   struct B {
      friend void f();
   };
}
void A::f() {}

int main(){
}

我认为 g++ 是正确的,因为 7.3.1.2/3 中的这个注释:

如果非本地类中的友元声明首先声明了一个类, 函数、类模板或函数模板97朋友是会员 最里面的封闭命名空间。朋友声明不 本身使名称对不合格的查找可见 ([basic.lookup.unqual]) 或限定查找 ([basic.lookup.qual])。 [ 注意:朋友的名字将在其命名空间中可见,如果 在命名空间范围内提供匹配的声明(之前或 在授予友谊的类定义之后)。  — 尾注 ] 如果一个 调用友元函数或函数模板,可以找到它的名字 通过考虑来自命名空间的函数的名称查找和 与函数参数类型相关的类 ([basic.lookup.argdep])。如果朋友声明中的名字是 既没有限定也没有模板ID,并且声明是一个函数 或详细的类型说明符,查找以确定是否 实体先前已声明不应考虑任何范围 在最里面的封闭命名空间之外。 [ 注:其他形式的 友元声明不能声明最内层的新成员 封闭命名空间,因此遵循通常的查找规则。 - 结尾 注意 ]

【问题讨论】:

标签: c++ namespaces language-lawyer friend


【解决方案1】:

你的这部分引用比你强调的注释更明确:

friend 声明本身不会使名称对非限定查找 ([basic.lookup.unqual]) 或限定查找 ([basic.lookup.qual]) 可见。

您的定义依赖于限定查找来查找已在命名空间内声明的函数。但该名称对合格的查找不可见。此代码应被拒绝。

这是一个相关的规则,见第 8.3 节 [dcl.meaning]

当 declarator-id 被限定时,该声明应引用该限定符所引用的类或命名空间的先前声明的成员(或者,在命名空间的情况下,该成员的内联命名空间集合的元素)命名空间)或其专业化;该成员不应仅由声明符 id 的嵌套名称说明符指定的类或命名空间范围内的 using 声明引入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 2016-10-20
    • 2022-10-12
    • 1970-01-01
    • 2016-09-15
    • 2012-12-22
    • 2015-10-25
    相关资源
    最近更新 更多