以下代码会产生编译错误(至少在最新版本的 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)):
(...) A declarator-id shall not be qualified except for the definition of a member function or static data member outside of its class, the definition or explicit instantiation of a function or variable of a namespace outside of its namespace, or the definition of an explicit specialization outside of its namespace, or the declaration of a friend function that is a member of another class or namespace. When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace).
(强调我的)这意味着你不能写
namespace a { }
void a::foo() { }
除非 a::foo
已在命名空间内使用非限定声明符进行声明。既然 friend 也不异常(exception),你也不能为 friend 这样做。
[namespace.memdef](C++11 中的 7.3.1.2 (3))中的脚注针对 friend 的特殊情况更明确地提到了这一点:
(...) If a friend declaration in a non-local class first declares a class or function95 the friend class or function is a member of the innermost enclosing namespace. (...)
95) This implies that the name of the class or function is unqualified.
关于c++ - 在友元声明中使用限定名称的规则是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27974521/