Re: преобразование одного enum в другой в C++ 14
От: Кодт Россия  
Дата: 05.09.24 11:10
Оценка: 12 (2)
Здравствуйте, sergey2b, Вы писали:

S>Подскажите пожалуйста как преобразовать одного enum в другой в C++ 14


Есть два аспекта: синтаксический и семантический. Как написать и что написать.

В семантическом есть два способа: логический и наивный.
Наивный — это любые варианты статик-каста (а по сути, реинтерпрет). Просто приводишь один underlying числовой тип в другой и скрещиваешь пальцы, что логика сохранилась.
Логический — это отображение одних числовых значений на другие. И вот тут начинается веселье. Можно свитчем, можно таблицей. Ещё вопрос, насколько устойчивы наборы значений в том и другом энуме (от версии к версии исходного кода), и как обрабатывать ошибки.

В синтаксическом есть два способа: инлайновое выражение и внешняя функция.
Неявное приведение через конструктор или оператор — для энумов невозможно.

Инлайновое выражение — это
static_cast<TargetEnum>(static_cast<std::underlying_type_t<TargetEnum>>(source_enum))

и оно работает, конечно, только для наивного преобразования.

Функция — тут уж свобода творчества
TargetEnum to_target_enum(SourceEnum source_enum) {
  switch(source_enum) {
    case SourceEnum::aaa : return TargetEnum::AAA;
    case SourceEnum::bbb : return TargetEnum::BBB;
    ...
    default: PANIC()
  }

  static const std::unordered_map<SourceEnum, TargetEnum> map{
    {SourceEnum::aaa, TargetEnum::AAA},
    {SourceEnum::bbb, TargetEnum::BBB},
    ...
  };
  return map.at(source_enum);

  using SourceInt = std::underlying_type_t<SourceEnum>;
  using TargetInt = std::underlying_type_t<TargetEnum>;
  auto source_int = static_cast<SourceInt>(source_enum);
  // на самом деле, тут условие гораздо более корявое и громоздкое, оно должно учитывать знаковые-беззнаковые сочетания всех сортов
  assert(std::numeric_limits<TargetInt>::min() <= source_int && source_int <= std::numeric_limits<TargetInt>::max());
  return static_cast<TargetEnum>(source_int);
}


Если энумы описаны на каком-то внешнем DSL (например, в протобуфе), то можно прибегнуть к имеющимся там средствам кодогенерации и рефлексии.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.