Supongamos que tengo una función de plantilla y dos clases
class animal {
}
class person {
}
template<class T>
void foo() {
if (T is animal) {
kill();
}
}
¿Cómo hago la verificación para T es animal? No quiero tener algo que verifique durante el tiempo de ejecución. Gracias
Respuestas:
Utilizar
is_same
:#include <type_traits> template <typename T> void foo() { if (std::is_same<T, animal>::value) { /* ... */ } // optimizable... }
Sin embargo, por lo general, ese es un diseño totalmente inviable y realmente desea especializarse :
template <typename T> void foo() { /* generic implementation */ } template <> void foo<animal>() { /* specific for T = animal */ }
Tenga en cuenta también que es inusual tener plantillas de funciones con argumentos explícitos (no deducidos). No es inaudito, pero a menudo hay mejores enfoques.
fuente
T
no se deduce, no hay mucho que puedas hacer. Puede dejar la plantilla principal sin implementar y crear una especialización, o puede agregar una aserción estática conis_same
.Creo que hoy en día es mejor usarlo, pero solo con C ++ 17.
#include <type_traits> template <typename T> void foo() { if constexpr (std::is_same_v<T, animal>) { // use type specific operations... } }
Si usa algunas operaciones específicas de tipo en el cuerpo de la expresión if sin
constexpr
, este código no se compilará.fuente
std::is_same<T, U>::value
podría usar más corto:std::is_same_v<T, U>
En C ++ 17, podemos usar variantes .
Para usar
std::variant
, debe incluir el encabezado:#include <variant>
Después de eso, puede agregar
std::variant
su código de esta manera:using Type = std::variant<Animal, Person>; template <class T> void foo(Type type) { if (std::is_same_v<type, Animal>) { // Do stuff... } else { // Do stuff... } }
fuente
type
que es el valor de tipoType
o una plantilla que no tiene sentido aquí)is_same_v
no es significativo en el contexto devariant
. El "rasgo" correspondiente esholds_alternative
.std::variant
es totalmente innecesario aquíPuede especializar sus plantillas en función de lo que se pasa a sus parámetros de esta manera:
template <> void foo<animal> { }
Tenga en cuenta que esto crea una función completamente nueva basada en el tipo que se pasa como
T
. Esto suele ser preferible ya que reduce el desorden y es esencialmente la razón por la que tenemos plantillas en primer lugar.fuente