Здравствуйте, 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 (например, в протобуфе), то можно прибегнуть к имеющимся там средствам кодогенерации и рефлексии.