我和我的同事都被这个问题困扰过几次。编译时
#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/