VS2015
和clang
可以编译这段代码,但是g++
无法通过编译。
namespace A {
struct B {
friend void f();
};
}
void A::f() {}
int main(){
}
我认为g++是正确的,因为7.3.1.2/3中的注释如下:
如果非局部类中的友元声明首先声明了一个类、函数、类模板或函数模板,那么友元就是最内层封闭命名空间的成员。友元声明本身不会使名称对未限定查找([basic.lookup.unqual])或限定查找([basic.lookup.qual])可见。【注意:如果在命名空间范围内提供了相应的匹配声明(在类定义授予友谊之前或之后),则友元的名称将在其命名空间中可见。-注】如果调用友元函数或函数模板,则可以通过考虑与函数参数类型相关联的命名空间和类的函数进行名称查找([basic.lookup.argdep])来找到它的名称。如果友元声明中的名称既不是限定的也不是模板ID,并且声明是函数或扩展类型说明符,则用于确定实体是否已经声明的查找不应考虑最内层封闭命名空间以外的任何作用域。【注意:其他形式的友元声明不能声明最内层封闭命名空间的新成员,因此遵循通常的查找规则。-注】