简体   繁体   中英

Match type in a list of type using C++ template

I need to match a type in a list of types at compile time using C++ template. Here is my code but it compiles to an error. Any idea how i can fix it?

template <typename T, typename X, typename... Rs>
struct match
{
    using test = typename std::conditional<std::is_same<T, X>::value, X, bool>::type;
    using more = typename match<T, Rs...>::type;
    using type = typename std::conditional<std::is_same<test, bool>::value, more, test>::type;
};

template <typename T>
struct match<T, bool>
{
    using type = bool;
};

match<int, int, float>::type x;

The error is:

1.cpp:99:45: error: wrong number of template arguments (1, should be at least 2)
  using more = typename match<T, Rs...>::type;

                                         ^

You should add a partial specialization to handle the case with exactly two template arguments, otherwise the instantiation of more will result in the instantiation of match with one template argument, thus an error occurs. Your match<T, bool> only handles the case where the last argument is bool , you should declare it as, for example,

template <typename T, typename X>
struct match<T, X>
{
    using type = typename std::conditional<std::is_same<T, X>::value, X, bool>::type;
};

In addition, I don't know what is the use of test . I think using more directly in the definition of type is sufficient:

template <typename T, typename X, typename... Rs>
struct match
{
    using more = typename match<T, Rs...>::type;
    using type = typename std::conditional<std::is_same<T, X>::value, X, more>::type;
};

This is still not the best solution, because it will result in the instantiation of more even if T matches X (in this case we can assert match::type is X without the instantiation of more ). To avoid the unnecessary instantiation, you can add an additional partial specialization:

template <typename T, typename... Rs>
struct match<T, T, Rs...>
{
    using type = T;
};

With this partial specialization, the primary template only matches the case where T is not X , thus you can further simplify the primary template as

template <typename T, typename X, typename... Rs>
struct match
{
    using type = typename match<T, Rs...>::type;
};

For completeness, the final solution would be:

#include <type_traits>

template <typename T, typename X, typename... Rs>
struct match
{
    using type = typename match<T, Rs...>::type;
};

template <typename T, typename... Rs>
struct match<T, T, Rs...>
{
    using type = T;
};

template <typename T, typename X>
struct match<T, X>
{
    using type = typename std::conditional<std::is_same<T, X>::value, X, bool>::type;
};

static_assert(std::is_same<int, match<int, int, float>::type>::value);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM