我已经被这个问题困扰了几次,我的同事也是如此。编译时

#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 命名空间中定义的类型,这会触发编译器尝试找到 boost::algorithm::find(RangeT& Input, const FinderT& Finder) 的 ADL。

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

最佳答案

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

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

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

10-12 14:58