How to generalize a template specialization for any variadic template type?
Asked Answered
K

1

6

I have the following type function to calculate whether some type T is part of the list of types in an std::tuple:

template<typename T, typename Tuple>
struct IsInTuple;

template<typename T, typename ...Ts>
struct IsInTuple<T, std::tuple<Ts...>>
{
  static constexpr bool value = std::disjunction_v<std::is_same<T, Ts>...>;
};

My question is, is it possible to generalize this function for any variadic template type taking a variadic list of types so that it not only works for std::tuple's, but for example also for std::variant's?

Kryska answered 4/4, 2024 at 8:55 Comment(1)
Yep, you just replace std::tuple with a template template parameter.Interpenetrate
F
8

Is it possible to generalize this function for any variadic template type taking a variadic list of types so that it not only works for std::tuples, but for example also for std::variants?

Yes, you can. Just use template template parameter to generalize the type traits.

template<typename T, typename Class> struct IsInTypeList;

template<typename T
       , template<typename...> class Class, typename... Ts>
struct IsInTypeList<T, Class<Ts...>>
{
    static constexpr bool value = (std::is_same_v<T, Ts> || ...);
                            // or std::disjunction_v<std::is_same<T, Ts>...>;
};

// Example usage
static_assert(IsInTypeList<int, std::tuple<int, float, double>>::value, "int is not in the tuple");
static_assert(!IsInTypeList<char, std::tuple<int, float, double>>::value, "char is in the tuple");
static_assert(!IsInTypeList<char, std::variant<int, float, double>>::value, "char is in the variant");

See live demo

Fokine answered 4/4, 2024 at 9:6 Comment(4)
this only works for template with type arguments. For example std::array will not match. Fortunately non type arguments are not that commonSodden
@Sodden question specifies "template type taking a variadic list of types", so we are fineNugatory
Just cosmetics, but I'd have preferred keeping the class and its arguments more closely toghether: typename T, template<typename...Ts> class Class, typename ...TsRousing
FWIW, I missed having to explicitly have to add typename ...Ts to the list of template arguments, otherwise Ts cannot be referenced in the implementation. Hard to figure out from reading cppreference.com unless I am missing something.Kryska

© 2022 - 2025 — McMap. All rights reserved.