This is a very interesting question. The simple answer is that it is literally undefined: the standard says nothing about this case.
To have a better example, consider this enum :
enum foo : bool { True=true, undefined };
In accordance with the standard:
[dcl.enum] / 2: [...] Defining an enumerator without an initializer gives the enumerator the value obtained by increasing the value of the previous enumerator by one.
Therefore, the value of foo::undefined in our example is 2 ( true+1 ). Which cannot be represented as a bool .
Is it badly formed?
No , according to the standard, this is absolutely true, only the non-fixed base type has a restriction on the impossibility of representing all counter values:
[dcl.enum] / 7: for an enumeration whose main type is not fixed, [...] If the integral type cannot represent all counter values, the enumeration is poorly formed.
It does not say anything about a fixed base type that cannot represent all counter values.
What is the meaning of the original oops and undefined question?
This is undefined : the standard says nothing about this case.
Possible values for foo::undefined :
- Maximum possible value (
true ): undefined and oops should be the maximum value of the base type. - Lowest possible value (
false ): The minimum value of the base type. Note. In signed integers, this will not match the current behavior for Integer overflow (undefined). - Random value (?): The compiler will select a value.
The problem with all of these values is that it can lead to two fields with the same value (for example, foo::True == foo::undefined ).
The difference between an initializer (for example, undefined=2 ) and an "implicit" initializer (for example, True=true, undefined )
In accordance with the standard:
[dcl.enum] / 5: If the base type is fixed, the type of each enumerator before the closing bracket is the base type, and the constant expression in the enumeration definition must be a constant type transformed by the base type.
In other words:
enum bar : bool { undefined=2 };
equivalently
enum bar : bool { undefined=static_cast<bool>(2) };
And then bar::undefined will be true . This is not so in the “implicit” initializer: this standard paragraph only speaks about this initializer, and not about the “implicit” initializer.
Summary
- Thus, it is possible that
enum with a fixed base type have underrepresented values. - Their value is undefined by standard.
According to the question and comments, this is not valid in GCC and clang, but is relevant for MSVS-2015 (with a warning).