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;
}
¿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;
};