c++ - 由于 ADL,对模板函数的调用不明确

标签 c++ visual-c++ templates argument-dependent-lookup

我和我的同事都被这个问题困扰过几次。编译时

#include <deque>
#include <boost/algorithm/string/find.hpp>
#include <boost/operators.hpp>

template< class Rng, class T >    
typename boost::range_iterator<Rng>::type find( Rng& rng, T const& t ) {
      return std::find( boost::begin(rng), boost::end(rng), t );
}

struct STest {
      bool operator==(STest const& test) const { return true; }
};

struct STest2 : boost::equality_comparable<STest2>   {
      bool operator==(STest2 const& test) const { return true; }
};

void main() {
      std::deque<STest> deq;
      find( deq, STest() ); // works
      find( deq, STest2() ); // C2668: 'find' : ambiguous call to overloaded function
}

...编译第二个查找时 VS9 编译器失败。这是因为 STest2 继承自 boost 命名空间中定义的类型,这会触发编译器尝试 ADL,它会找到 boost::algorithm::find(RangeT& Input, const FinderT&查找器)

一个明显的解决方案是在调用 find(…) 前加上“::”,但为什么这是必要的?全局命名空间中存在完全有效的匹配项,那么为什么要调用 Argument-Dependent Lookup?任何人都可以解释这里的基本原理吗?

最佳答案

ADL 不是“正常”重载解析失败时使用的回退机制,ADL 找到的函数与正常查找找到的函数一样可行。

如果 ADL 是一个后备解决方案,那么您可能很容易陷入陷阱,即使有另一个函数更匹配但只能通过 ADL 可见,但使用了一个函数。在(例如)运算符重载的情况下,这看起来特别奇怪。您不希望通过 operator== 比较两个对象的类型,当适当的 operator== 中存在完美的 operator== 时,它们可以隐式转换为命名空间。

关于c++ - 由于 ADL,对模板函数的调用不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3675829/

相关文章:

c++ - 在子类中调用父函数

c++ - 如何找到模板函数接受的参数数量?

Perl:模板工具包的替代品

c++ - 错误 : could not deduce template argument

c++模板偏特化成员函数

c++ - 无法打开fstream C++文件,即使它与.cpp位置相同

c++ - 如何将用户输入的 char* 附加到 const char* 的初始化中

c++ - 为什么我的 for 循环给出错误 : X does not name a type

c - Windows 中 char * 和 LPSTR 的区别

windows - Visual C++ 无法找到 PVOID、DWORD、ULONG 等 "Windows types"