我在Stroustrup book(第4版)第396和397页中给出的参数依赖查找(ADL)示例下面重现:
namespace N {
struct S { int i; };
void f(S);
void g(S);
void h(int);
};
struct Base {
void f(N::S);
};
struct D : Base {
void mf(N::S);
void g(N::S x)
{
f(x); // call Base::f()
mf(x); // call D::mf()
h(1); // error: no h(int) available
}
};
上面的评论是正确的(我已经测试过了),但这似乎与作者在下一段中所说的不一致:
在标准中,参数依赖查找的规则是措辞 就相关名称空间而言(iso§3.4.2)。基本上是:
- 如果参数是类成员,则关联的命名空间是类本身(包括其基类)和类的 封闭名称空间。
- 如果参数是命名空间的成员,则关联的命名空间是封闭的命名空间。
- 如果参数是内置类型,则没有关联的命名空间。
在示例中,类型为x
的{{1}}不是类N::S
的成员,也不是其基类D
的成员。但它是Base
的成员。根据上面的第二个项目,函数namespace N
应该是被调用的函数,而不是N::f(S)
。
上述结果似乎也不符合标准第3.4.2p2段中的第二个子弹,该子弹说:
如果T是类类型(包括联合),则其关联的类是: 班级本身;它所属的成员,如果有的话;和它的 直接和间接基类。其关联的命名空间是 其关联类是成员的名称空间。此外, 如果T是类模板特化,其关联的命名空间和 类还包括:名称空间和与之关联的类 为模板类型参数提供的模板参数的类型 (不包括模板模板参数);任何名称空间 模板模板参数是成员;以及任何类别 用作模板模板参数的成员模板是成员。
答案 0 :(得分:4)
3.4.2 / 3 让
X
成为非限定查找(3.4.1)生成的查找集,让Y
成为依赖于参数的查找集 查找(定义如下)。如果X
包含
- 类成员的声明,或
- 块范围函数声明,它不是using声明或
- 既不是函数也不是函数模板的声明
然后Y为空。否则...
基本上,当普通查找找到成员函数或本地(块范围)函数声明(或者不是函数的东西)时,ADL不会启动。当普通查找找到一个独立的命名空间范围函数,或者什么都没找到时,它确实会启动。