Ответ 1
Что такое цвет в соответствии со стандартом?
Ответ с цитатой из Стандарта:
[expr.static.cast]/10
Значение интегрального или перечисляемого типа может быть явно преобразовано в тип перечисления. Значение не изменяется, если исходное значение находится в диапазоне значений перечисления (7.2). В противном случае результирующее значение не указано (и может быть не в этом диапазоне).
Посмотрите на диапазон значений перечисления: [dcl.enum]/7
Для перечисления, базовый тип которого фиксирован, значения перечисления являются значениями базового типа.
До CWG 1766
Следовательно, для data[0] == 100
результирующее значение указывается (*), а не Undefined Поведение (UB). В более общем плане, когда вы отбрасываете базовый тип в тип перечисления, никакое значение в data[0]
не может привести к UB для static_cast
.
После CWG 1766 См. дефект CWG 1766. Параграф [expr.static.cast] p10 был усилен, поэтому теперь do вызывать UB, если вы выставляете значение, выходящее за пределы отображаемого диапазона перечисления, к типу перечисления.
(*) char
требуется шириной не менее 8 бит, но не требуется unsigned
. Максимальное сохраняемое значение должно быть не менее 127
за приложение E стандарта C99.
Сравните с [expr]/4
Если во время оценки выражения результат не определен математически или нет в диапазоне отображаемых значений для его типа, поведение undefined.
Таким образом, это может легко привести к UB, если значение было достаточно большим, например. static_cast<Color>(10000);
.
Теперь оператор switch
:
[stmt.switch]/2
Условие должно быть целочисленного типа, типа перечисления или типа класса. [...] Выполняются интегральные рекламные акции.
[conv.prom]/4
Значение типа без подписки, базовый тип которого фиксирован (7.2), может быть преобразован в prvalue его базового типа. Более того, если интегральное продвижение может быть применено к его базовому типу, то присвоение неперечисленного типа перечисления, базовый тип которого является фиксированным, также может быть преобразовано в prvalue продвинутого базового типа.
Примечание. Основной тип области с enum без enum-base - int
. Для неперечисленных перечислений базовый тип определяется реализацией, но не должен превышать int
, если int
может содержать значения всех счетчиков.
Для неперечисленного перечисления это приводит к тому, что /1
Значение целочисленного типа, отличного от
bool
,char16_t
,char32_t
илиwchar_t
, чей целочисленный ранг преобразования (4.13) меньше рангаint
, может быть преобразован в prvalue typeint
, еслиint
может представлять все значения типа источника; в противном случае исходное prvalue может быть преобразовано в prvalue типаunsigned int
.
В случае перечисления без подписки здесь мы будем иметь дело с int
. Для перечислений (enum class
и enum struct
) интегральная акция не применяется. В любом случае интегральное продвижение также не приводит к UB, поскольку сохраненное значение находится в диапазоне базового типа и в диапазоне int
.
[stmt.switch]/5
Когда выполняется оператор
switch
, его состояние оценивается и сравнивается с каждой константой случая. Если одна из констант случая равна значению условия, управление передается в оператор, следующий за соответствующей меткойcase
. Если константаcase
соответствует условию, и если есть меткаdefault
, управление переходит к выражению, помеченному меткойdefault
.
Надпись default
должна быть удалена.
Примечание. Можно было бы еще раз взглянуть на оператор сравнения, но он явно не используется в упомянутом "сравнении". На самом деле, нет никакого намека на то, что в нашем случае будет введен UB для областей с ограниченным или неперечисленным перечислением.
Как бонус, делает ли стандарт какие-либо гарантии по этому поводу, но с простым перечислением?
Является ли область enum
областью действия, здесь не имеет никакого значения. Однако имеет значение, является ли основной тип фиксированным. Полный [decl.enum]/7:
Для перечисления, основной тип которого является фиксированным, значения перечисления являются значениями базового типа. В противном случае для перечисления, где e min является наименьшим перечислителем, а e max является наибольшим, значения перечисления являются значениями в диапазоне b min до b max, определяемый следующим образом: пусть
K
be1
для двухкомпонентного представления и0
для представления одного дополнения или знака. b max - наименьшее значение, большее или равно max (| e min | -K
, | e max |) и равно до 2 M - 1, гдеM
- неотрицательное целое число. b min равно нулю, если e min неотрицательно и - (b max +K
) в противном случае.
К счастью, ваш наименьший перечислитель перечисляет red = 0x1
, поэтому max (| e min | - K
, | e max |) равен | e <югу > тахсуб > | в любом случае, который равен yellow = 0x2
. Наименьшее значение, большее или равное 2
, равное 2 M - 1 для положительного целого M
, есть 3
(2 2 - 1), (Я думаю, что цель состоит в том, чтобы разрешить диапазон до 1-битного шага.) Отсюда следует, что b max 3
и bmin есть 0
.
Следовательно, 100
будет находиться за пределами диапазона перечисления, а static_cast
создаст неуказанное значение, которое может привести к UB согласно [expr]/4..