c++ c++11 metaprogramming sfinae

c++ - Usando SFINAE para verificar si el tipo está completo o no



c++11 metaprogramming (3)

Esta pregunta ya tiene una respuesta aquí:

¿Es posible verificar con SFINAE si el tipo está completamente definido?

P.ej

template <class T> struct hash; template <> struct hash<int> {}; // is_defined_hash_type definition... enum Enum { A, B, C, D }; static_assert ( is_defined_hash_type<int> ::value, "hash<int> should be defined"); static_assert (! is_defined_hash_type<Enum>::value, "hash<Enum> should not be defined");

La solución no debe modificar la estructura hash .


Lo mejor que se me ocurrió es lo siguiente, que requiere al menos un typedef con un nombre común en toda la especialización de hash :

template <class T> struct hash; template <> struct hash<int> { typedef int value_type; }; template<class T> constexpr bool is_defined_hash_type(typename hash<T>::value_type) { return true; } template<class T> constexpr bool is_defined_hash_type(T) { return false; } int main() { static_assert ( is_defined_hash_type< int >(0), "hash<int> should be defined"); static_assert (! is_defined_hash_type< double>(0), "hash<Enum> should not be defined"); return 0; }

La sintaxis es bastante fea, debido al parámetro agregado (necesario para activar SFINAE). Si crees que puede ser el camino a seguir, intentaré limpiarlo aún más.

Descargo de responsabilidad: de ninguna manera soy un experto en C ++ 11, por lo que es posible que haya perdido algunos puntos con las nuevas funciones. En ese caso dispara a voluntad e intentaré corregir la respuesta.


No es posible. La razón es que deberías definir is_defined_hash_type<T> pero solo puede haber una definición. Pero si más adelante define T , la definición de is_defined_hash_type<T> un resultado diferente, por lo tanto, una definición diferente, y eso no está permitido. Es una violación de la ODR (regla de una definición).


Puede hacer un rasgo de tipo is_complete , usando el hecho de que está mal formado para evaluar sizeof(T) para un tipo incompleto T :

template <typename T> struct is_complete_helper { template <typename U> static auto test(U*) -> std::integral_constant<bool, sizeof(U) == sizeof(U)>; static auto test(...) -> std::false_type; using type = decltype(test((T*)0)); }; template <typename T> struct is_complete : is_complete_helper<T>::type {};

y is_defined_hash_type<T> para verificar el is_defined_hash_type<T> al determinar si el hash<T> está completo. ( Vive en Coliru )

Como dice Daniel en su respuesta, la utilidad de tal cosa es limitada. El rasgo no prueba realmente si el tipo está completo en el punto en el código en el que realiza la consulta, comprueba si el tipo se completó en el punto en el programa donde el rasgo se creó por primera vez para un tipo dado.