Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ : Check if the template type is one of the variadic template types [duplicate]

Let's say we have function:

template <typename Kind, typename... Kinds> void foo(){...};

What is the simplest way to check if the type 'Kind' is one of the types 'Kinds' in C++ (including C++1z)?

like image 640
Michał Avatar asked Dec 05 '15 21:12

Michał


People also ask

What are variadic templates in C++?

Variadic templates in C++. Finally, there's a way to write functions that take an arbitrary number of arguments in a type-safe way and have all the argument handling logic resolved at compile-time, rather than run-time. Variadic templates can be used for much more than just functions that take an arbitrary number of arguments;

What is a variadic template pack in Python?

The pack can have arbitarary number of parameters having different types. At the end of compile-time, a variadic template function is translated into multiple solid functions that each of them accepts a certain number of parameters with certain types. There is no explicit for-loop commands to iterate the pack parameters.

Should I be worried about the performance of variadic templates?

If you're concerned with the performance of code that relies on variadic templates, worry not. As there's no actual recursion involved, all we have is a sequence of function calls pre-generated at compile-time. This sequence is, in practice, fairly short (variadic calls with more than 5-6 arguments are rare).

What are variadic arguments in C++?

Douglas Gregor and Jaakko Järvi came up with this feature for C++. Variadic arguments are very similar to arrays in C++. We can easily iterate through the arguments, find the size (length) of the template, can access the values by an index, and can slice the templates too.


1 Answers

You could use the following type trait:

template <typename...>
struct is_one_of {
    static constexpr bool value = false;
};

template <typename F, typename S, typename... T>
struct is_one_of<F, S, T...> {
    static constexpr bool value =
        std::is_same<F, S>::value || is_one_of<F, T...>::value;
};

Live Demo

Update C++17

Using the C++17 pattern expansion there is no need for auxiliar class anymore

template <typename Kind, typename... Kinds> void foo(){
    /* The following expands to :
     * std::is_same_v<Kind, Kind0> || std::is_same_v<Kind, Kind1> || ... */
    if constexpr ((std::is_same_v<Kind, Kinds> || ...)) {
        // expected type
    } else {
        // not expected type
    }
};

Live Demo

like image 171
101010 Avatar answered Oct 22 '22 03:10

101010