studio reales proyectos programacion libro introducción incluye herramientas fundamentos fuente español código con avanzado aplicaciones c++ templates types

c++ - reales - Recupere el tipo de plantilla más interno dentro de la propia plantilla



libro de android studio en español pdf (5)

A menos que me esté perdiendo algo, me especializaría parcialmente en una plantilla para facilitar las cosas.

template<typename T> struct A { using type = T; }; template<typename T> struct A<A<T>> { using type = typename A<T>::type; }; int main() { A<double>::type a = 5.0; A<A<double>>::type d = 3.0; A<A<A<double>>>::type c = 9.5; return 0; }

Muestra en vivo

¿Es posible recuperar el tipo más interno de plantillas apiladas del mismo tipo desde dentro de la plantilla ? Me gustaría recuperar el tipo double en el siguiente ejemplo:

template<typename T> struct is_a : std::false_type {}; template<typename T> struct A { using type = std::conditional_t< is_a<T>::value, T::type, // if it''s an A, go deeper T>; // if not, we''re done }; template<typename T> struct is_a<A<T>> : std::true_type {}; int main() { A<A<A<A<A<double>>>>>::type d = 3.0; return 0; }

Fue motivado por esta question . Además, encontré esta post , lo que indica que puede tener algo que ver con la typename template palabras clave de typename o template , pero no pude hacer que funcione.


Además de su error tipográfico de perder un nombre de typename , el problema aquí:

using type = std::conditional_t< is_a<T>::value, T::type, // if it''s an A, go deeper T>; // if not, we''re done

Es que std::conditional no es cortocircuito. Cuando T no tiene type miembro, esto causará un error.

Puede escribir una función meta para extraer recursivamente el tipo interno:

template<class T> struct extract_type { using type = T; }; template<class T> class A; template<class T> struct extract_type<A<T>> { using type = typename extract_type<T>::type; }; template<typename T> struct A { using type = typename extract_type<T>::type; }; int main() { A<A<A<A<A<double>>>>>::type d = 3.0; return 0; }


Alternativa a la respuesta (correcta) de Marco. Es posible que desee poner algo de esta lógica de selección de tipo en una clase de rasgos:

// step 1 - predeclare the template A template<typename T> struct A; // define a default specialisation of a traits type template<class T> struct ATraits { using type = T; }; // specialise the traits for the A<T> case template<class T> struct ATraits<A<T>> { using type = typename A<T>::type; }; // now define the A template default specialisation template<typename T> struct A { using type = typename ATraits<T>::type; }; int main() { A<A<A<A<A<double>>>>>::type d = 3.0; return 0; }


El truco habitual para hacerlo con su enfoque original es aplazar la evaluación:

template<class T> struct type_identity { using type = T; }; template<typename T> struct A { using type = typename std::conditional_t< is_a<T>::value, T, type_identity<T>>::type; };


Puede usar enable_if y SFINAE para seleccionar el tipo más interno así:

template<typename T, class Enable = void> struct A { using type = T; }; template<typename T> struct A<T, std::enable_if_t<!std::is_same_v<T, typename T::type>>> { using type = typename T::type; };