以下代码由Visual C ++ 2013和2015成功编译,但gcc和clang报告错误。我想知道C ++ 11标准是否有适用于这种情况的东西,除了下面的引用允许在处理朋友类声明时有些模棱两可,或者它只是一个VC错误。
有问题的行是朋友类声明。
class Friend {
public:
Friend();
};
void globalFun();
namespace { // Does not matter if it is not anonymous.
class InNamespace {
// "friend Friend" or "friend class ::Friend" works in gcc and clang.
friend class Friend; // <- ???
friend void ::globalFun(); // Even VC does not allow unqualified name
class Private {};
};
}
Friend::Friend() {
InNamespace::Private a;
(void) a;
}
void globalFun() {
InNamespace::Private a;
(void) a;
}
int main() {
Friend f;
globalFun();
return 0;
}
gcc和clang抱怨InNamespace::Private
在Friend
构造函数的范围内是私有的。这听起来很合理,因为在Friend
和C ++ 11标准状态的最内部封闭命名空间的全局命名空间中声明了InNamespace
7.3.1.2命名空间成员定义[namespace.memdef]
3 ...如果朋友声明中的名称既不合格也不是模板ID,声明是函数或精心设计的类型说明符,用于确定实体是否先前已声明的查找不应考虑最内层封闭命名空间之外的任何范围。
C ++ 14和C ++ 17的10.3.1.2节中的相同措辞。
我感到困惑的是,关于函数Visual Studio遵循引用的句子,但它放宽了类的规则。看起来后者被视为精心设计的类型说明符,而不是匿名命名空间中类的前向声明。是否存在C ++标准的另一部分,可以将其视为最内部封闭命名空间之外的名称查找权限?