3

我在 Stroustrup 书(第 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,具有 typeN::S的 不是 class 的成员D,也不是其 base的成员Base。但它是namespace N. 根据上面的第二个项目符号,该函数N::f(S)应该是被调用的函数,而不是Base::f().

上面的结果似乎也与标准中第 3.4.2p2 段中的第二个项目符号不一致,其中说:

如果 T 是类类型(包括联合),则其关联的类是:类本身;它所属的类别(如有的话);及其直接和间接基类。其关联名称空间是其关联类是其成员的名称空间。此外,如果 T 是类模板特化,则其关联的命名空间和类还包括: 与为模板类型参数(不包括模板模板参数)提供的模板实参类型相关联的命名空间和类;任何模板模板参数都是其成员的命名空间;以及用作模板模板参数的任何成员模板是其成员的类。

4

1 回答 1

4

3.4.2/3X为非限定查询(3.4.1)Y产生的查询集,令为参数依赖查询产生的查询集(定义如下)。如果X包含

  • 类成员的声明,或
  • 不是 using 声明的块范围函数声明,或
  • 既不是函数也不是函数模板的声明

那么 Y 为空。除此以外...

所以基本上,当普通查找找到成员函数或本地(块范围)函数声明(或不是函数的东西)时,ADL 不会启动。当普通查找找到一个独立的命名空间范围函数时,或者当它什么也没找到时,它会启动。

于 2013-10-06T14:15:29.207 回答