Consider a alias template declaration, depending on a single template parameter that can have a finite number of values, like a class enum
.
I would like to a employ using to define a type alias for every value of the class enum
.
One way of implementing is to use std::conditional
:
class enum color { white, red, blue };
struct A {};
struct B {};
struct C {};
template <color c>
using data = std::conditional_t<c == color::white, A, std::conditional_t<c == color::red, B, C>>;
Obviously, when the class enum color
is expanded to new values, one needs an additional nested std::conditional
, which is rather cumbersome.
I am looking for a solution to express this in a "scalable" way, that is, such that on expanding the class enum
one has to do a minimal work.
Something like
template <class c>
using data = some_struct<c, A, B, C>;
where some_struct
"select" the type A, B, C depending on the first parameter c.
How can I implement that (in a scalable way)?
CodePudding user response:
You can use specialization. Primary and helper:
template <color c> struct data;
template <color c> using data_t = data<T>::type;
Then for each case its one specialization to be written:
template <> struct data<color::white> { using type = A; }
template <> struct data<color::red> { using type = B; }
// ...
Adding a new enum mapped to a new type is then just adding a specialization
CodePudding user response:
One way you can do this is to create a tuple of the types to pick from and match those up with the order of the enum you have. Then you can just get the type from the tuple at the index of the value of the enumeration. That would look like
using type_set = std::tuple<A, B, C>;
template <color c>
using data_t = typename std::tuple_element<static_cast<size_t>(c), type_set>::type;
Now all you need to do is add types to the tuple that defines type_set
as you add enumerations to color
. You can see it working in this live example which uses an error message to tell you what data_t<color::red>
resolves to the type B
.