Supposons que j'ai une fonction template et deux classes
class animal {
}
class person {
}
template<class T>
void foo() {
if (T is animal) {
kill();
}
}
Comment faire le chèque pour T is animal? Je ne veux pas avoir quelque chose qui vérifie pendant le temps d'exécution. Merci
Utilisation is_same
:
#include <type_traits>
template <typename T>
void foo()
{
if (std::is_same<T, animal>::value) { /* ... */ } // optimizable...
}
Habituellement, c'est une conception totalement irréalisable, cependant, et vous voulez vraiment spécialiser:
template <typename T> void foo() { /* generic implementation */ }
template <> void foo<animal>() { /* specific for T = animal */ }
Notez également qu’il est inhabituel d’avoir des modèles de fonction avec des arguments explicites (non déduits). Ce n'est pas du jamais vu, mais il y a souvent de meilleures approches.
Je pense qu'aujourd'hui, il est préférable d'utiliser, mais seulement avec C++ 17.
#include <type_traits>
template <typename T>
void foo() {
if constexpr (std::is_same_v<T, animal>) {
// use type specific operations...
}
}
Si vous utilisez des opérations spécifiques au type dans if expression body sans constexpr
, ce code ne sera pas compilé.
En C++ 17, nous pouvons utiliser variantes .
Utiliser std::variant
, vous devez inclure l'en-tête:
#include <variant>
Après cela, vous pouvez ajouter std::variant
dans votre code comme ceci:
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...
}
}
Vous pouvez spécialiser vos modèles en fonction de ce qui est passé dans leurs paramètres, comme ceci:
template <> void foo<animal> {
}
Notez que cela crée une fonction entièrement nouvelle basée sur le type passé en tant que T
. Ceci est généralement préférable car cela réduit l'encombrement et est essentiellement la raison pour laquelle nous avons des modèles en premier lieu.