哪个命名空间确实包含此友元函数的声明?

Wak*_*zil 4 c++ lookup namespaces argument-dependent-lookup c++11

friend以下功能不受普通查找(§7.3.1.2/ 3)发现,但是由ADL(§3.4.2/ 4第二个项目符号点)发现,所以代码编译和正常执行(活例子).但是该函数f未在任何名称空间中声明.例如,如果您尝试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);
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*cow 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
};
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

另一个引用(7.3.1命名空间定义)

3首先在名称空间中声明的每个名称都是该名称空间的成员.如果非本地类中的友元声明首先声明了类,函数,类模板或函数模板98,则该友元是最内层封闭命名空间的成员.友元声明本身不会使名称对非限定查找(3.4.1)或限定查找(3.4.3)可见.[注意:如果在命名空间范围内提供匹配的声明(在类定义授予友谊之前或之后),则朋友的名称将在其命名空间中可见.-end note]如果调用了友元函数或函数模板,则可以通过名称查找找到其名称,该名称查找考虑名称空间中的函数和与函数参数类型相关联的类(3.4.2).如果友元声明中的名称既不是限定语句也不是模板标识,并且声明是函数或详细类型说明符,则确定实体是否先前已声明的查找不应考虑最内层封闭命名空间之外的任何范围.[注意:其他形式的友元声明不能声明最内层封闭命名空间的新成员,因此遵循通常的查找规则. - 尾注]

我想提一下,在括号中包含一个函数名会抑制依赖于参数的查找.

对于此代码

int main()
{
    A::X x;
    ( f )(x);
}
Run Code Online (Sandbox Code Playgroud)

函数f将无法找到.