Это полностью безопасно, потому что:
- ваш
enum class
- это перечисление в области видимости;
- ваше перечисление имеет фиксированный базовый тип
: char
;
- поэтому значения вашего перечисления являются значениями типа
char
;
- так что приведение значения char к перечислению полностью допустимо.
Здесь C ++ 17 стандартных кавычек, которые соответствуют приведенным выше утверждениям:
[dcl.enum] / 2: (...) Клавиши enum enum class
и enum struct
являются
семантически эквивалентный; тип перечисления, объявленный с одним из
это перечисление scoped , а его перечислители ограничены
счетчики.
[dcl.enum] / 5: (...) Каждое перечисление также имеет базовый тип.
базовый тип может быть явно указан с помощью enum-base. (...)
В обоих этих случаях базовый тип называется
исправлена . (...)
[dcl.enum] / 8: Для перечисления, базовый тип которого фиксирован,
значения перечисления являются значениями базового типа . (...)
[expr.static.cast] / 10 Значение целочисленного типа или типа перечисления может быть
явно преобразован в полный тип перечисления. Если
тип перечисления имеет фиксированный базовый тип, значение является первым
преобразовать в этот тип путем интегрального преобразования, если необходимо, а затем
к типу перечисления. [expr.cast] / 4 Преобразования, выполненные
const_cast, static_cast, static_cast, за которым следует const_cast,
reinterpret_cast, reinterpret_cast, сопровождаемый const_cast, может быть
выполняется с использованием приведенной нотации явного преобразования типов. (...)
Если преобразование можно интерпретировать более чем одним из перечисленных способов
выше используется интерпретация, которая появляется первой в списке (...)
Выводы будут другими, если базовый тип не будет фиксированным. В этом случае будет применяться оставшаяся часть [dcl.enum] / 8: более или менее сказано, что если вы не находитесь в пределах наименьшего и наибольшего перечислителей перечисления, вы не уверены, что значение может быть представлял.
См. Также вопрос Разрешено ли перечислению иметь незарегистрированное значение? , которое является более общим (C ++ & C), но не использует перечисление с областью видимости или указанный базовый тип.
А здесь фрагмент кода для использования значений перечисления, для которых не определен перечислитель:
switch((Foo)bar2()) {
case Foo::UNKNOWN: std::cout << "UNKNWON" << std::endl;break;
case Foo::ENUM1: std::cout << "ENUM1" << std::endl;break;
case Foo::ENUM2: std::cout << "ENUM2" << std::endl;break;
case Foo::ENUM3: std::cout << "ENUM3" << std::endl;break;
case static_cast<Foo>('D'): std::cout << "ENUM-SPECIAL-D" << std::endl;break;
default: std::cout << "DEFAULT" << std::endl;break;
}