c++ - near - mva
¿Por qué este caso de ADL está funcionando? (2)
¿Cómo sabe find_type
dónde está la función typemap
?
El argumento que recibe no proviene de ese espacio de nombres, sino del std
nombres std
.
#include <type_traits>
#include <memory>
namespace lib {
template<typename T>
struct find_type {
using type = decltype(typemap(std::declval<T>()));
};
}
namespace test {
struct Test {};
auto typemap(std::unique_ptr<Test>) -> int;
}
static_assert(std::is_same<int, lib::find_type<std::unique_ptr<test::Test>>::type>::value, "");
¿Cómo puede funcionar este código? ¿Cuál es la regla que permite esto?
Lo probé con GCC 6.3 y clang 3.9.1.
El argumento que recibe no proviene de ese espacio de nombres, sino del espacio de nombres estándar.
¡No todo!
using type = decltype(typemap(std::declval<T>()));
Esto es:
using type = decltype(typemap(std::declval<std::unique_ptr<test::Test>>()));
Hay una test::
allí, por lo que también se busca la test
del espacio de nombres.
En el estándar C ++ N4618 §3.4.2 [basic.lookup.argdep] (2.2)
Si T es un tipo de clase (incluidas las uniones), sus clases asociadas son: la clase en sí misma; la clase de la que es miembro, en su caso; y sus clases básicas directas e indirectas. Sus espacios de nombres asociados son los espacios de nombres de cierre más internos de sus clases asociadas. Además, si T es una especialización de plantilla de clase, sus espacios de nombres y clases asociados también incluyen: los espacios de nombres y clases asociados con los tipos de argumentos de plantilla proporcionados para los parámetros de tipo de plantilla (excluyendo los parámetros de plantilla de plantilla); los espacios de nombres de los cuales cualquier argumento de plantilla de plantilla son miembros; y las clases de las cuales todas las plantillas miembro utilizadas como argumentos de plantilla de plantilla son miembros.
El argumento de typemap
es std::unique_ptr<test::Test>
, por lo que la test
espacio de nombres se considera para la búsqueda de nombres.