Załóżmy, że mam funkcję szablonu i dwie klasy
class animal {
}
class person {
}
template<class T>
void foo() {
if (T is animal) {
kill();
}
}
Jak sprawdzić, czy T to zwierzę? Nie chcę mieć czegoś, co sprawdza się w czasie wykonywania. Dzięki
Odpowiedzi:
Zastosowanie
is_same
:#include <type_traits> template <typename T> void foo() { if (std::is_same<T, animal>::value) { /* ... */ } // optimizable... }
Zwykle jest to jednak całkowicie niewykonalny projekt i naprawdę chcesz się specjalizować :
template <typename T> void foo() { /* generic implementation */ } template <> void foo<animal>() { /* specific for T = animal */ }
Zauważ również, że nietypowe jest posiadanie szablonów funkcji z jawnymi (niewyprowadzonymi) argumentami. Nie jest to niespotykane, ale często istnieją lepsze podejścia.
źródło
T
nie jest to wydedukowane, niewiele można zrobić. Możesz pozostawić podstawowy szablon niezaimplementowany i utworzyć specjalizację lub możesz dodać statyczne potwierdzenie za pomocąis_same
.Myślę, że dziś lepiej jest używać, ale tylko z C ++ 17.
#include <type_traits> template <typename T> void foo() { if constexpr (std::is_same_v<T, animal>) { // use type specific operations... } }
Jeśli użyjesz operacji specyficznych dla typu w treści wyrażenia if bez
constexpr
, ten kod nie zostanie skompilowany.źródło
std::is_same<T, U>::value
ciebie możesz użyć krótszego:std::is_same_v<T, U>
W C ++ 17 możemy używać wariantów .
Aby użyć
std::variant
, musisz dołączyć nagłówek:#include <variant>
Następnie możesz dodać
std::variant
swój kod w następujący sposób: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... } }
źródło
type
które są wartością typuType
lub szablonem, który nie ma tu sensu)is_same_v
nie ma znaczenia w kontekścievariant
. Odpowiednią „cechą” jestholds_alternative
.std::variant
jest tu zupełnie niepotrzebneMożesz specjalizować swoje szablony na podstawie tego, co jest przekazywane do ich parametrów, w następujący sposób:
template <> void foo<animal> { }
Zauważ, że tworzy to całkowicie nową funkcję na podstawie typu przekazanego jako
T
. Zwykle jest to preferowane, ponieważ zmniejsza bałagan i jest przede wszystkim powodem, dla którego mamy szablony na pierwszym miejscu.źródło