WhatABeautifulWorld
WhatABeautifulWorld

Reputation: 3388

How to check for the type of a template parameter?

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

Upvotes: 148

Views: 217469

Answers (6)

I think todays, it is better to use, but this only works with C++17 or later.

#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.

Upvotes: 70

andriy-byte
andriy-byte

Reputation: 33

use c++ concepts https://en.cppreference.com/w/cpp/language/constraints

for example class who recive only char types

#include <concepts>

 template<typename Type>
    concept CharTypes = std::is_same<Type, char>::value ||
                        std::is_same<Type, wchar_t>::value || std::is_same<Type, char8_t>::value ||
                        std::is_same<Type, char16_t>::value || std::is_same<Type, char32_t>::value;

template<CharTypes T>
    class Some{};

and yes, this not working


    Some<int> s;

Upvotes: 2

scai
scai

Reputation: 21509

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)) { /* ... */ }
}

Upvotes: 13

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...
    }
}

Upvotes: 7

template boy
template boy

Reputation: 10490

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.

Upvotes: 10

Kerrek SB
Kerrek SB

Reputation: 477600

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.

Upvotes: 197

Related Questions