Me ha picado un par de veces este problema y también mis colegas. Al compilarLlamada ambigua a la función de plantilla debido a ADL
#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
}
... el compilador VS9 falla al compilar el segundo hallazgo. Esto se debe al hecho de que STest2
hereda de un tipo que está definido en el espacio de nombres boost que hace que el compilador pruebe ADL que encuentra boost::algorithm::find(RangeT& Input, const FinderT& Finder)
.
Una solución obvia es prefijar la llamada a find(…)
con "::
", pero ¿por qué es necesario? Existe una coincidencia perfectamente válida en el espacio de nombres global, entonces ¿por qué invocar Argument-Dependent Lookup? ¿Alguien puede explicar el razonamiento aquí?
Tenga en cuenta que la coincidencia no es perfecta. Una función que no sea de plantilla 'find (std :: deque, STest);' sería una mejor coincidencia. –
MSalters
@MSalters: tienes razón, por supuesto. La coincidencia en el espacio de nombres global no es perfecta. Creo que esperaba que ADL fuera una excepción, y solía encontrar una coincidencia estrictamente mejor en un espacio de nombres más remoto. Las respuestas muestran que esto es un malentendido. – Sebastian
Mi pregunta es por qué ADL está encontrando una función dentro de 'boost :: algorithm' cuando el argumento es una clase en el espacio de nombres global, que hereda de una clase en el espacio de nombres' boost :: detail' ... y la respuesta es una 'using algorithm :: find' en el encabezado' 'que lleva la función al espacio de nombres' boost'. ¿Podría ser esto un defecto? ¿No debería ser esto al menos opcional? –