[namespace.memdef]/3(重点是我的):
如果非本地类中的朋友声明首先声明了一个类, 函数,类模板或函数模板 106 朋友是成员 最里面的封闭命名空间。朋友声明不 本身会使名称对不合格的查找(6.4.1)可见,或者 合格查询(6.4.3)。 [注意:朋友的名字将是 如果在以下位置提供了匹配的声明,则在其名称空间中可见 命名空间范围(在类定义授予之前或之后) 友谊)。 —尾注]如果朋友功能或功能模板是 被称为,其名称可以通过考虑以下内容的名称查找来找到 命名空间和与类型相关联的类中的函数 函数参数(6.4.2)。 如果朋友声明中的姓名是 既不是合格的也不是template-id,并且声明是一个函数 或详尽的类型说明符,以确定是否 实体已事先声明,不考虑任何范围 最内层的封闭命名空间之外。 [注意:其他形式的 朋友声明不能声明最内层成员的新成员 封闭名称空间,因此遵循通常的查找规则。 —尾注 ] [示例:...
code below可以正确执行,而不管好友声明是否是其命名空间中的第一个声明。
#include<iostream>
namespace N{
struct A;
void f(A&); // If you comment out this declaration, i.e., if the
// friend declaration turns out to be the first
// declaration in namespace N, the code will still
// execute correctly, i.e., printing the same result
// below.
struct A {
friend void f(A& ra) { std::cout << "friend void f(A&)\n" << ra.i; }
private:
int i = 100;
};
}
N::A a;
int main(){
f(a);
}
此代码段打印出以下内容:
friend void f(A&)
100
答案 0 :(得分:2)
可以找到ADL,因为您从命名空间N
传递了一个参数。可以将示例更改为此:
namespace N{
void f(int); // If you comment out this declaration, i.e., if the
// friend declaration turns out to be the first
// declaration in namespace N, the code will fail to compile.
struct A {
friend void f(int) { std::cout << "friend void f()\n"; }
private:
int i = 100;
};
}
int main(){
N::f(1);
}