友元函数的参数依赖查找
Argument dependent lookup for friend functions
考虑以下几点:
namespace N {
struct A { };
struct B {
B() { }
B(A const&) { }
friend void f(B const& ) { }
};
}
int main() {
f(N::B{}); // ok
f(N::A{}); // error
}
在第一种情况下,案例成功 - 我们考虑 N::B
的关联命名空间并找到 N::f(B const&)
。太好了。
第二种情况失败。为什么?根据[namespace.memdef]:
If a friend
declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. [...] If a friend function or function template
is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2).
N::A
的关联命名空间是N
,f
是其中的一个成员,为什么查不到呢?
这是因为 f
没有在关联的 class 中声明。当参数类型为 B
时,B
是关联的 class,但当参数类型为 A
.
时则不是
我引用 [basic.lookup.argdep]/4,强调我的:
When considering an associated namespace, the lookup is the same as the lookup performed when the
associated namespace is used as a qualifier (3.4.3.2) except that:
— Any using-directives in the associated namespace are ignored.
— Any namespace-scope friend functions or friend function templates declared in associated classes are
visible within their respective namespaces even if they are not visible during an ordinary lookup (11.3).
— All names except those of (possibly overloaded) functions and function templates are ignored.
考虑以下几点:
namespace N {
struct A { };
struct B {
B() { }
B(A const&) { }
friend void f(B const& ) { }
};
}
int main() {
f(N::B{}); // ok
f(N::A{}); // error
}
在第一种情况下,案例成功 - 我们考虑 N::B
的关联命名空间并找到 N::f(B const&)
。太好了。
第二种情况失败。为什么?根据[namespace.memdef]:
If a
friend
declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. [...] If a friend function or function template is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2).
N::A
的关联命名空间是N
,f
是其中的一个成员,为什么查不到呢?
这是因为 f
没有在关联的 class 中声明。当参数类型为 B
时,B
是关联的 class,但当参数类型为 A
.
我引用 [basic.lookup.argdep]/4,强调我的:
When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that:
— Any using-directives in the associated namespace are ignored.
— Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup (11.3).
— All names except those of (possibly overloaded) functions and function templates are ignored.