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_tinteger conversion rank (4.13) less rank ofintcan converted prvalue of typeintifintcan represent values of source type; otherwise, source prvalue can converted prvalue of typeunsigned int.
in case of unscoped enumeration, dealing ints 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
switchstatement executed, condition evaluated , compared each case constant. if 1 of case constants equal value of condition, control passed statement following matchedcaselabel. if nocaseconstant matches condition, , if theredefaultlabel, control passes statement labeleddefaultlabel.
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
k1two's complement representation ,0one's complement or sign-magnitude representation. bmax smallest value greater or equal max(|emin| −k, |emax|) , equal 2m − 1,mnon-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