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.
how to define in C++20 a concept to check if a type matches any of the types in a type-list
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());
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
}
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>>());