依赖于参数的查找和函数模板

Argument-dependent lookup and function templates

本文关键字:函数模板 查找 参数 依赖于      更新时间:2023-10-16

下面是一个例子:

#include <string>
#include <algorithm>
#include <memory>
using std::string;
int main()
{
    string str = "This is a string";
    // ok: needn't using declaration, ADL works
    auto it = find(str.begin(), str.end(), 'i');
    // error: why ADL doesn't work?
    std::shared_ptr<string> sp = make_shared<string>(str);
}

当我试图编译这个程序时,编译器抱怨道:

error: no template named 'make_shared'; did you mean 'std::make_shared'?
        std::shared_ptr<string> sp = make_shared<string>(str); // error...
                                     ^~~~~~~~~~~
                                     std::make_shared

我猜第一个函数find不需要using声明,因为依赖于参数的查找(ADL):编译器将在string所在的命名空间(即std)中搜索find的定义。但对于第二个函数make_sharedADL似乎不起作用:我必须使用std::make_sharedusing声明。我知道两个函数模板的定义不同:前者将其模板参数之一(typename T或类似的东西)作为函数参数类型,并返回相同的类型。后者以函数参数包作为函数参数,返回类型为另一个模板参数。这是禁用ADL的区别吗?或者你能帮忙回答这个问题并提供一些参考资料吗?

参数相关查找适用于不合格的函数调用表达式。这对于"普通"函数和函数模板专门化都是正确的。

然而,当您为模板函数提供显式模板参数时,表达式在语法上看起来不像函数调用:

foo<3>(x)  //   "foo less than three?"

这就是为什么这些病例不会触发ADL。然而,一旦名称已知为模板,ADL就会适用!

template <int> void foo();
foo<double, 5, T>(x);   // uses ADL

当我们用<>显式指定模板参数时,模板方法不使用ADL,除非作用域中有可见的模板方法(同名)。