I need a type_chooser
trait that would look like
using chosen_type = type_chooser<bool1, T1, bool2, T2, ....., boolN, TN, Telse>;
and would work like
if (bool1) return T1;
else if (bool2) return T2;
...
else if (boolN) return TN;
else return Telse;
How can this be implemented (c++20)?
It would be nice if it could accept even number of arguments as well, in which case it would work like:
if (bool1) return T1;
else if (bool2) return T2;
...
else if (boolN) return TN;
else COMPILE_TIME_ERROR;
Mixed non-type/type parameters like that just aren't available for an arbitrary number of arguments.
You can try changing the syntax. Here are some options:
// One argument for the bool and the type
template<bool B, typename T>
struct Case;
template<typename T>
struct Else;
using chosen_type = type_chooser<Case<bool1, T1>, Case<bool2, T2>, ....., Case<boolN, TN>, Else<Telse>>;
// Maybe written as
using chosen_type = first_with_member_type<std::enable_if<bool1, T1>, std::enable_if<bool2, T2>, ..., std::enable_if<boolN, TN>, std::type_identity<TElse>>;
// Type-only arguments
using chosen_type = type_chooser<std::bool_constant<bool1>, T1, std::bool_constant<bool2>, T2, ..., std::bool_constant<boolN, TN>, Telse>;
// Or non-type-only arguments
using chosen_type = type_chooser<bool1, std::type_identity<T1>{}, bool2, std::type_identity<T2>{}, ..., boolN, std::type_identity<TN>{}, std::type_identity<TElse>{}>;
// Move all the bools to a single parameter
using chosen_type = type_chooser<std::integer_sequence<bool,
bool1, bool2, bool3, ..., boolN
>, T1, T2, T3, ..., TN, TElse
>;
// Write out your if/else chain
using chosen_type = decltype([]{
if constexpr (bool1) return std::type_identity<T1>{};
else if constexpr (bool2) return std::type_identity<T2>{};
...
else if constexpr (boolN) return std::type_identity<TN>{};
else return std::type_identity<Telse>{};
}())::type;
// If you have a known max number of types
template<
bool B1 = false, typename T1 = void, bool B2 = false, typename T2 = void,
bool B3 = false, typename T3 = void, ...,
bool BN = false, typename TN = void, bool B(N+1) = false, typename T(N+1) = void
>
struct type_chooser;
using chosen_type = type_chooser<bool1, T1, bool2, T2, ..., boolN, TN, true, TElse>;