How to check for the type of a template parameter?
C++TemplatesC++ Problem Overview
Suppose I have a template function and two classes
class animal {
}
class person {
}
template<class T>
void foo() {
if (T is animal) {
kill();
}
}
How do I do the check for T is animal? I don't want to have something that checks during the run time. Thanks
C++ Solutions
Solution 1 - C++
Use is_same
:
#include <type_traits>
template <typename T>
void foo()
{
if (std::is_same<T, animal>::value) { /* ... */ } // optimizable...
}
Usually, that's a totally unworkable design, though, and you really want to specialize:
template <typename T> void foo() { /* generic implementation */ }
template <> void foo<animal>() { /* specific for T = animal */ }
Note also that it's unusual to have function templates with explicit (non-deduced) arguments. It's not unheard of, but often there are better approaches.
Solution 2 - C++
I think todays, it is better to use, but only with C++17.
#include <type_traits>
template <typename T>
void foo() {
if constexpr (std::is_same_v<T, animal>) {
// use type specific operations...
}
}
If you use some type specific operations in if expression body without constexpr
, this code will not compile.
Solution 3 - C++
You can specialize your templates based on what's passed into their parameters like this:
template <> void foo<animal> {
}
Note that this creates an entirely new function based on the type that's passed as T
. This is usually preferable as it reduces clutter and is essentially the reason we have templates in the first place.
Solution 4 - C++
In C++17, we can use variants.
To use std::variant
, you need to include the header:
#include <variant>
After that, you may add std::variant
in your code like this:
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...
}
}
Solution 5 - C++
std::is_same()
is only available since C++11. For pre-C++11 you can use typeid()
:
template <typename T>
void foo()
{
if (typeid(T) == typeid(animal)) { /* ... */ }
}