Рассмотрим объявление шаблона псевдонима, зависящее от одного параметра шаблона, который может иметь конечное число значений, например class enum
.
Я хотел бы использовать использование для определения псевдонима типа для каждого значения class enum
.
Один из способов реализации — использовать 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>>;
Очевидно, что когда class enum color
расширяется до новых значений, нужна дополнительная вложенная std::conditional
, что довольно громоздко.
Я ищу решение, чтобы выразить это «масштабируемым» способом, то есть таким, чтобы при расширении class enum
нужно было выполнять минимальную работу.
Что-то вроде
template <class c>
using data = some_struct<c, A, B, C>;
где some_struct
"выбрать" тип A, B, C в зависимости от первого параметра c.
Как я могу реализовать это (масштабируемым способом)?
вы всегда выбираете между A
, B
и C
, а если вы добавляете значение, то добавляете D
? Или это любой 3 тип? Я не уверен, что вы хотите получить some_struct
, или это просто ваша попытка получить data
?
@dfrib правильно, я изменил заголовок и текст
@ 463035818_is_not_a_number Я намерен добавить новый элемент цвета x и соответствующий struct D
, чтобы data<x> = D
.
Один из способов сделать это — создать кортеж типов для выбора и сопоставить их с порядком перечисления, которое у вас есть. Затем вы можете просто получить тип из кортежа по индексу значения перечисления. Это будет выглядеть как
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;
Теперь все, что вам нужно сделать, это добавить типы в кортеж, который определяет type_set
, когда вы добавляете перечисления в color
. Вы можете увидеть, как это работает в этом живом примере, который использует сообщение об ошибке, чтобы сообщить вам, что data_t<color::red>
разрешается в тип B
.
Вы можете использовать специализацию. Основные и вспомогательные:
template <color c> struct data;
template <color c> using data_t = data<T>::type;
Тогда для каждого случая записывается одна его специализация:
template <> struct data<color::white> { using type = A; }
template <> struct data<color::red> { using type = B; }
// ...
Добавление нового перечисления, сопоставленного с новым типом, означает просто добавление специализации.
Не то чтобы это шаблон псевдонима, а не директива использования.