普通查找(第7.3.1.2 / 3节)找不到下面的friend
函数,但是ADL(§3.4.2/ 4第二个项目符号点)找到了f
函数,因此代码编译并正常执行(live example)。但是函数f(x);
未在任何名称空间中声明。例如,如果您尝试通过这些调用::f(x);
,A::f(x);
或A::X::f(x);
替换来电#include <iostream>
namespace A {
class X {
int i;
friend void f(X x) { std::cout << x.i << '\n'; }
public:
X():i(101){}
};
}
int main()
{
A::X x;
f(x);
}
,则代码将无法编译。哪个命名空间确实包含此友元函数的声明?标准是否对此有所说明?
{{1}}
答案 0 :(得分:5)
来自C ++标准
11.3朋友
6如果和,可以在类的朋友声明中定义函数 只有当类是非本地类(9.8)时,函数名才是 不合格,该函数具有命名空间范围。 [例如:
class M { friend void f() { } // definition of global f, a friend of M,
// not the definition of a member function
};
-end example]
另一个引用(7.3.1命名空间定义)
3在名称空间中首先声明的每个名称都是其成员 命名空间。如果非本地类中的朋友声明首先声明 朋友是一个类,函数,类模板或函数模板98 最内层封闭命名空间的成员。 朋友声明 本身不会使名称对非限定查找可见(3.4.1) 或合格的查找(3.4.3)。 [注意:朋友的名字将是 如果在提供匹配的声明,则在其命名空间中可见 命名空间范围(在类定义授予之前或之后) 友谊)。 -end note] 如果朋友的功能或功能模板是 调用时,可以通过查找的名称查找找到其名称 来自名称空间的函数和与类型相关联的类 函数参数(3.4.2)。如果朋友声明中的名字是 既不是限定的也不是模板ID,声明是一个函数 或者是一个精心设计的类型说明符,查找是否确定 实体先前已宣布不得考虑任何范围 在最里面的封闭命名空间之外。 [注:其他形式的 朋友声明不能声明最里面的新成员 封闭命名空间,因此遵循通常的查找规则。 - 注意 ]
我想提一下,在括号中包含一个函数名会抑制依赖于参数的查找。
对于此代码
int main()
{
A::X x;
( f )(x);
}
将找不到函数f。