我已经被这个问题困扰了几次,我的同事也是如此。编译时
#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/