【问题标题】:Argument-dependent lookup and function templates [duplicate]依赖于参数的查找和函数模板
【发布时间】:2016-03-24 23:02:47
【问题描述】:

这是一个例子:

#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 所在的命名空间(即stdfind 的定义。但是对于第二个函数make_shared,似乎ADL 不起作用:我必须改用std::make_sharedusing 声明。我知道两个函数模板的定义是不同的:前者将其模板参数之一(typename T 或类似的东西)作为函数参数类型并返回相同的类型。后者将函数参数包作为函数参数,其返回类型是另一个模板参数。这是禁用ADL 的区别吗?或者您能帮忙回答问题并提供一些参考资料吗?

【问题讨论】:

  • 第一个用法是脆的。您依赖于迭代器类型位于std 的未指定情况。如果在另一天迭代器类型是const char *,它将无法编译。
  • 我知道省略using 声明是一种脆弱的方式。就像与第二个的比较一样>_
  • @chihyang:更好的例子是begin(str)
  • @chihyang:这根本不是我的意思。在您的示例中重要的是 iterator. 的类型

标签: c++ templates argument-dependent-lookup function-templates


【解决方案1】:

依赖于参数的查找适用于不合格的函数调用表达式。这对于“普通”函数和函数模板特化都是如此。

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

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

这就是为什么这些情况不会触发 ADL。但是,一旦名称​​已知是模板,ADL 就适用!

template <int> void foo();

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

【讨论】:

  • 嗯......我在你的答案中尝试了这种方式,它确实工作正常!但这真的感觉很奇怪:声明另一个我们永远不会使用的函数模板只是为了通知编译器我们正在使用的名称是一个模板!为什么 ADL 这么奇怪?在 C++ Primer 上,它需要不到 3 页。但现在看来,这似乎是一个巨大的陷阱!
  • @chihyang:是的。但我希望你能及时发现这在实际应用中并不是什么大问题。
  • @chihyang; ADL 的主要用途是创建自定义点。您不应将其用于示例中的“直接”代码。所以你接触到这种怪异的次数应该相对较少。
  • 是的。我总是省略库算法的using 声明。也许我应该在了解 ADL 后改掉这个坏习惯。谢谢。
【解决方案2】:

当我们用&lt;&gt; 显式指定模板参数时,模板方法不使用ADL,除非范围内有可见的模板方法(同名)。

【讨论】:

  • 不完全。首先,这仅适用于具有明确指定模板参数的函数调用。其次,如果您在范围内还有另一个函数模板,则 ADL 确实适用。限制本质上是语法上的,而不是深刻的:如果没有现有的声明,调用表达式在语法上看起来不像函数调用。
  • @KerrekSB:确实如此。改写了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-14
  • 2020-04-20
  • 2013-03-30
相关资源
最近更新 更多