Basically, given
enum class Color : int { R, G, B };
Color c;
is there any way for c
to end up holding something other than R
, G
, B
? Or, in other words, an underlying int
other than 0
, 1
, or 2
?
I know that the declaration of c
above leaves it uninitialize, and that
Color c{};
would initialize it to R
/0
.
However, I've discovered that if the definition of the enumeration were
enum calss Color : int { R = 1, G, B };
then the {}
-initialized c
would have value 0
, which does not correspond to any of R
/G
/B
(I've verified that c == Color::enumerator
returns false
for any enumerator
chosen from R
, G
, B
; and static_cast<int>(c)
is 0).
Now this, looks a bit edgy to me: if 0
does not underlay any of the enumerators, then why does {}
-initialization give that value to the underlaying int
?
Color
is a scoped enumeration type, therefore its underlying type is fixed. (In your case you have explicitly specified it asint
, but scoped enumerations also default toint
when not explicitly specified. You can also explicitly specify an underlying type for unscoped enumerations.)For an enumeration whose underlying type is fixed, all values of the underlying type are valid values for the enumeration. That is,
Color
can hold anyint
value. If it holds a value that none of its enumerators have, that just means that it won't compare equal to any of its enumerators. This may seem a bit strange, but the alternative would have been to give the program undefined behaviour, and most people would agree that we don't need any more undefined behaviour in C++.(For an enumeration whose underlying type is not fixed, the rules are a bit more complicated. It is usually still possible to give them values that don't correspond to any enumerator, but the range of allowable values is narrower. Going outside that range results in undefined behaviour.)