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, or wchar_t integer conversion rank (4.13) less rank of int can converted prvalue of type int if int can represent values of source type; otherwise, source prvalue can converted prvalue of type unsigned 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 switch statement executed, condition evaluated , compared each case constant. if 1 of case constants equal value of condition, control passed statement following matched case label. if no case constant matches condition, , if there default label, control passes statement labeled default 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

Popular posts from this blog

ios - UICollectionView Self Sizing Cells with Auto Layout -

node.js - ldapjs - write after end error -

DOM Manipulation in Wordpress (and elsewhere) using php -