为什么不能在 class 中引用转发声明的朋友 class?
Why can't forward declared friend class be referred in the class?
以下代码无法编译:
struct X {
friend class Y;
Y* ptr;
};
cppreference描述的情况为
... If the name of the class that is used in the friend declaration is
not yet declared, it is forward declared on the spot.
如果"spot"是声明好友关系的地方,那么声明成员Y* ptr
应该没问题。为什么不编译?标准中哪里禁止这样做?
这是网站上的一个错误。它与标准相矛盾,标准说友谊声明不能代替前向声明:
7.3.1.2.3 Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.
关于名称对非限定或限定查找不可见的部分实质上意味着该名称的行为不像前向声明。
除了@dasblinkenlight 的回答之外,3.3.2 Point of declaration lit. 10 中的注释明确指出朋友声明不引入(因此不引入 "forward declare")class 名称:
10 [ Note: Friend declarations refer to functions or classes that are
members of the nearest enclosing namespace, but they do not introduce
new names into that namespace ([namespace.memdef]).
修复此代码的一种方法是简单地 add class
keyword:
struct X {
friend class Y;
class Y* ptr;
};
如果 X
在全局范围内,这将在全局范围内转发声明 class Y
。
以下代码无法编译:
struct X {
friend class Y;
Y* ptr;
};
cppreference描述的情况为
... If the name of the class that is used in the friend declaration is not yet declared, it is forward declared on the spot.
如果"spot"是声明好友关系的地方,那么声明成员Y* ptr
应该没问题。为什么不编译?标准中哪里禁止这样做?
这是网站上的一个错误。它与标准相矛盾,标准说友谊声明不能代替前向声明:
7.3.1.2.3 Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.
关于名称对非限定或限定查找不可见的部分实质上意味着该名称的行为不像前向声明。
除了@dasblinkenlight 的回答之外,3.3.2 Point of declaration lit. 10 中的注释明确指出朋友声明不引入(因此不引入 "forward declare")class 名称:
10 [ Note: Friend declarations refer to functions or classes that are members of the nearest enclosing namespace, but they do not introduce new names into that namespace ([namespace.memdef]).
修复此代码的一种方法是简单地 add class
keyword:
struct X {
friend class Y;
class Y* ptr;
};
如果 X
在全局范围内,这将在全局范围内转发声明 class Y
。