§3.4.1/3 有以下示例:
typedef int f;
namespace N
{
struct A
{
friend void f(A &);
operator int();
void g(A a)
{
int i = f(a);
}
};
}
编译时没有错误(参见live example ),因为编译器在声明中的名称的N::A::f(A&)
普通查找中看不到友元声明,根据 §7.3.1.2/3 这是正确的。f
int i = f(a);
§7.3.1.2/3(重点是我的):
在命名空间中首先声明的每个名称都是该命名空间的成员。如果非本地类中的友元声明首先声明了一个类或函数,则友元类或函数是最内层封闭命名空间的成员。在该命名空间范围内(在授予友谊的类定义之前或之后)提供匹配声明之前,未限定查找 (3.4.1) 或限定查找 (3.4.3) 无法找到朋友的名称。
现在,如果我们包含声明
struct A;
void f(A&);
在上面的代码片段中namespace N
,在 之前,struct A
代码将正确地发出错误(参见实时示例),因为现在该函数是通过在表达式::f(A&)
中的名称的普通查找找到的,这符合 §7.3.1.2/3。f
int i = f(a);
但是,如果我们包含声明
void f(A&);
在namespace N
之后,代码出人意料地struct A
没有发出任何错误,请参见live example。