c++ - What happens if you static_cast invalid value to enum class? -
consider c++11 code:
enum class color : char { red = 0x1, yellow = 0x2 } // ... char *data = readfile(); color color = static_cast<color>(data[0]);
suppose data[0] 100. color set according standard? in particular, if later do
switch (color) { // ... red , yellow cases omitted default: // handle error break; }
does standard guarantee default hit? if not, proper, efficient, elegant way check error here?
edit:
as bonus, standard make guarantees plain enum?
what color set according standard?
answering quote standard:
[expr.static.cast]/10
a value of integral or enumeration type can explicitly converted enumeration type. value unchanged if original value within range of enumeration values (7.2). otherwise, resulting value unspecified (and might not in range).
let's range of enumeration values: [dcl.enum]/7
for enumeration underlying type fixed, values of enumeration values of underlying type.
before cwg 1766 therefore, data[0] == 100
, resulting value specified(*), , no undefined behaviour (ub) involved. more generally, cast underlying type enumeration type, no value in data[0]
can lead ub static_cast
.
after cwg 1766 see cwg defect 1766. [expr.static.cast]p10 paragraph has been strengthened, do invoke ub if cast value outside representable range of enum enum type.
(*) char
required @ least 8 bit wide, isn't required unsigned
. maximum value storable required @ least 127
per annex e of c99 standard.
compare [expr]/4
if during evaluation of expression, result not mathematically defined or not in range of representable values type, behavior undefined.
so could lead ub if value big enough, e.g. static_cast<color>(10000);
.
now, switch
statement:
[stmt.switch]/2
the condition shall of integral type, enumeration type, or class type. [...] integral promotions performed.
[conv.prom]/4
a prvalue of unscoped enumeration type underlying type fixed (7.2) can converted prvalue of underlying type. moreover, if integral promotion can applied underlying type, prvalue of unscoped enumeration type underlying type fixed can converted prvalue of promoted underlying type.
note: underlying type of scoped enum w/o enum-base int
. unscoped enums underlying type implementation-defined, shall not larger int
if int
can contain values of enumerators.
for unscoped enumeration, leads /1
a prvalue of integer type other
bool
,char16_t
,char32_t
, orwchar_t
integer conversion rank (4.13) less rank ofint
can converted prvalue of typeint
ifint
can represent values of source type; otherwise, source prvalue can converted prvalue of typeunsigned int
.
in case of unscoped enumeration, dealing int
s here. scoped enumerations (enum class
, enum struct
), no integral promotion applies. in way, integral promotion doesn't lead ub either, stored value in range of underlying type , in range of int
.
[stmt.switch]/5
when
switch
statement executed, condition evaluated , compared each case constant. if 1 of case constants equal value of condition, control passed statement following matchedcase
label. if nocase
constant matches condition, , if theredefault
label, control passes statement labeleddefault
label.
the default
label should hit.
note: 1 take @ comparison operator, not explicitly used in referred "comparison". in fact, there's no hint introduce ub scoped or unscoped enums in our case.
as bonus, standard make guarantees plain enum?
whether or not enum
scoped doesn't make difference here. however, make difference whether or not underlying type fixed. complete [decl.enum]/7 is:
for enumeration underlying type fixed, values of enumeration values of underlying type. otherwise, enumeration emin smallest enumerator , emax largest, values of enumeration values in range bmin bmax, defined follows: let
k
1
two's complement representation ,0
one's complement or sign-magnitude representation. bmax smallest value greater or equal max(|emin| −k
, |emax|) , equal 2m − 1,m
non-negative integer. bmin 0 if emin non-negative , −(bmax +k
) otherwise.
fortunately, enum's smallest enumerator red = 0x1
, max(|emin| − k
, |emax|) equal |emax| in case, yellow = 0x2
. smallest value greater or equal 2
, equal 2m - 1 positive integer m
3
(22 - 1). (i think intent allow range extent in 1-bit-steps.) follows bmax 3
, bmin 0
.
therefore, 100
outside range of enum, , static_cast
produce unspecified value, lead ub per [expr]/4.
Comments
Post a Comment