I would like to define a concept that indicates a type is one of several supported types. I can do this by repeatedly listing the types with std::same_as<U>
:
#include <concepts>
template <typename T>
concept IsMySupportedType = std::same_as<T, int32_t> || std::same_as<T, int64_t> || std::same_as<T, float> || std::same_as<T, double>;
Is there a more concise way to write this without repeating the std::same_as
concept?
CodePudding user response:
This can be done using a variadic helper concept (taken from the cppreference for std::same_as
):
template <typename T, typename... U>
concept IsAnyOf = (std::same_as<T, U> || ...);
This can be used to define the desired concept as follows:
template <typename T>
concept IsMySupportedType = IsAnyOf<T, std::int32_t, std::int64_t, float, double>;
Note that the initial T
on the right-hand side is important.
The resulting concept can be used as expected:
static_assert(IsMySupportedType<float>);
static_assert(!IsMySupportedType<std::int8_t>);
Compiling example: https://godbolt.org/z/6dE9r1EY6
CodePudding user response:
I would use std::disjunction
which has the upside that it is short-circuiting:
"if there is a template type argument Bi
with bool(Bi::value) != false
, then instantiating disjunction<B1, ..., BN>::value
does not require the instantiation of Bj::value
for j > i
"
template <class T, class... U>
concept any_of = std::disjunction_v<std::is_same<T, U>...>;
template <class T>
concept IsMySupportedType = any_of<T, std::int32_t, std::int64_t, float, double>;