依赖于参数的查找 - 何时完成,搜索的内容以及如何强制(或阻止)它?

时间:2013-01-05 05:17:53

标签: c++ argument-dependent-lookup

我无法理解依赖于参数(Koenig)查找的规则。

请考虑以下代码:

#include <iostream>

using namespace std;

namespace adl
{
    struct Test { };
    void foo1(Test const &) { cout << "ADL used (foo1)" << endl; }
    void foo2(Test const &) { cout << "ADL used (foo2)" << endl; }
    void foo3(Test const &) { cout << "ADL used (foo3)" << endl; }
}

struct foo1
{
    foo1() { }

    template<class T>
    foo1(T const &) { cout << "ADL not used (foo1)" << endl; }

    template<class T>
    void operator()(T const &) const { cout << "ADL not used (foo3)" << endl; }
};

template<class T> void foo2(T const &)
{ cout << "ADL not used (foo2)" << endl; }

int main()
{
    adl::Test t;
    foo1 foo3;
    (foo1(t));
    (foo2(t));
    (foo3(t));
}

它的输出是:

  

未使用ADL(foo1
  使用ADL(foo2
  未使用ADL(foo3

我希望他们所有人都使用ADL,但我很惊讶他们中只有一些人这样做了。

ADL规则背后的(可能是血腥的,我知道的)细节是什么?
我很清楚这个概念,但细节是我遇到的麻烦。

搜索哪些范围,何时搜索,以及何时未搜索?

是否可以判断是否使用ADL而无需在给定的代码行之前查看 所有 #include'd文件?我希望仿函数和函数在[不]屏蔽ADL方面的行为方式相同,但显然它们没有。

有没有办法强制 ADL在没有自动完成的情况下(例如上面的)并且你不知道类的命名空间(例如在模板中)?

1 个答案:

答案 0 :(得分:5)

你的问题不是真的与参数相关的查找。首先,参数依赖查找只有在进行不合格的函数查找时才可能进入图像。调用foo1(t) foo1时是一种类型,并调用其模板化构造函数。类似地,foo3(t)是一个限定查找,因为foo3是一个对象,并且在对象的类foo1中查找函数调用操作符。参数查找进入图片的唯一地方是调用foo2(t)查找候选者的地方:

  1. ::foo2<adl::Test>(adl::Test const&)
  2. ::adl::foo2(adl::Test const&)
  3. 这两个函数被移交给重载解析,因为两个函数同样匹配非模板函数获胜。

    你的问题实际上是三个问题:

    1. 名称查找的血淋淋的细节太宽泛,因此,这个问题是要求写一篇我忽略的文章。
    2. 你的第二个问题扩展到另外三个问题,只有一个似乎相关:
      1. 搜索哪些范围?在函数定义中查找非限定函数名时,规则取决于任何名称是否为从属名称。如果没有这样的名称(即,在非模板代码或模板代码中,可以在第一阶段确定名称),则查找名称,包含名称空间和与其参数关联的名称空间。否则,仅在关联的命名空间中查找名称。
    3. 可以强制参数依赖查找吗?如果存在至少一个参数但是发现的名称可能是更好的匹配,则总是为非限定函数查找完成。当然,你需要调用一个不合格的函数,否则就不会这样做。