EN VI

how to define in C++20 a concept to check if a type matches any of the types in a type-list?

2024-03-12 17:30:05
how to define in C++20 a concept to check if a type matches any of the types in a type-list

I want to define a concept in C++ (<= C++20) to check if a type matches any of the types define in a type-list struct.

The following is my attempt so far:

template<typename... Types>
struct TypeList {};

using SupportedTypes = TypeList<int, bool, float, long>;
    
template<typename T, typename... Types>
concept IsAnyOf = (std::is_same_v<T, Types> || ...);
    
static_assert(IsAnyOf<bool, SupportedTypes>);

I have also tried using:

template<typename T, typename... Types>
concept IsAnyOf = std::disjunction_v<std::is_same<T, Types>...>;

But my static assertion fails:

Static assertion failed
because 'IsSupportedType<_Bool, SupportedTypes>' evaluated to false
because 'std::is_same_v<_Bool, meta::TypeList<int, _Bool, float, long> >' evaluated to false

I understand it probably has to do with the fact that I'm passing SupportedTypes to the concept without properly unpacking the types inside it, and hence in the static assertion I'm checking if bool is the same as SupportedTypes, as opposed to checking if bool is the same as any of the types inside SupportedTypes; but I can't get it to work nonetheless.

Solution:

how to define in C++20 a concept to check if a type matches any of the types in a type-list

Method 1

You can change the program to as shown below. This is more readable than method 2.

template<typename... Types>
struct TypeList {};

template <typename T, typename List>
concept IsAnyOf = []<typename... Types>(TypeList<Types...>) 
{
   return (std::is_same_v<Types, T> || ...);
}(List());

Working demo


This is how you would use it:

using SupportedTypes = TypeList<double, float, std::string, bool>;

int main() 
{
    std::cout << IsAnyOf<bool, SupportedTypes>; //true
    std::cout << IsAnyOf<char, SupportedTypes>; //false
}

Method 2

Note there are also other ways to do this like using std::tuple and std::inxex_sequence as shown in this alternative.

template <typename T, typename Typelist>
concept is_any_of = []<std::size_t... Indices>(std::index_sequence<Indices...>) 
{
   return (std::is_same_v<std::tuple_element_t<Indices, Typelist>, T> || ...);
}(std::make_index_sequence<std::tuple_size_v<Typelist>>());

Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login