I've been bitten by this problem a couple of times and so have my colleagues. When compiling
#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 } ...the VS9 compiler fails when compiling the second find. This is due to the fact that STest2 inherits from a type that is defined in boost namespace which triggers the compiler to try ADL which finds boost::algorithm::find(RangeT& Input, const FinderT& Finder).
An obvious solution is to prefix the call to find(…) with "::" but why is this necessary? There is a perfectly valid match in the global namespace, so why invoke Argument-Dependent Lookup? Can anybody explain the rationale here?
find(std::deque<STest>, STest);would be a better match.boost::algorithmwhen the argument is a class in the global namespace, that inherits from a class in theboost::detailnamespace... and the answer is ausing algorithm::findin the<boost/algorithm/string/find.hpp>header that brings the function into theboostnamespace. Could this be a defect? Should this not be at the very least optional?std::operator<<(ostream& , string)for classes implementingstd::ostream.