24

Is the default initialization/construction of enum classes defined behavior?

Here is a minimal example(Try Online)

enum class ALPHA{
    X = 0,
    Y = 1,
    Z = 2,
};

int main()
{
    ALPHA a = ALPHA(); // use default constructor
    ALPHA b{}; // use default initialization
    std::cout <<static_cast<int>(a) << std::endl; // 0
    std::cout <<static_cast<int>(b) << std::endl; // 0
    return 0;
}

I get zero in both cases. So does the default initialization pick the first enum type(eg. here X = 0) always? I know that it is UB for standard enums but Im not sure about the semantics for enum classes? I looked this up on CPPReference too but didnt find any relevant information about it - Is it possible to get a standard reference too?

tangy
  • 3,056
  • 2
  • 25
  • 42
  • 1
    Is this a duplicate of https://stackoverflow.com/questions/17630967/user-defined-c11-enum-class-default-constructor? I think at least that answer also answers your question. – Griffon26 Dec 22 '18 at 17:51
  • 1
    I think it does somewhat answer my question - that theres no default constructor defined and this case will default initialize according to int- but (1) there is no standard reference (2) is it guaranteed to default initialize according to the native type(https://stackoverflow.com/questions/3803153/what-are-primitive-types-default-initialized-to-in-c) – tangy Dec 22 '18 at 17:56
  • 1
    The sections he mentions are from the standard. What kind of reference are you looking for? – Griffon26 Dec 22 '18 at 18:05
  • My bad - ok then I think that answers the question. Should I just delete this? – tangy Dec 22 '18 at 18:14
  • 1
    Now that I have looked at some different versions of the standard, I see that there has been a change on this point. Apparently C++03 said zero-initialized where C++11 says it's uninitialized. I don't have official releases of the standards to check exactly which versions specify what. – Griffon26 Dec 22 '18 at 18:24
  • One more question.. what do you mean by "default initialize according to the native type"? – Griffon26 Dec 22 '18 at 18:26
  • wrong term, i meant that does it follow zero initialization rules. – tangy Dec 22 '18 at 20:07
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/185661/discussion-between-tangy-and-griffon26). – tangy Dec 22 '18 at 20:10

2 Answers2

12

[expr.type.conv]/1 A simple-type-specifier (10.1.7.2) or typename-specifier (17.6) followed by a parenthesized optional *expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.

[expr.type.conv]/2 ... Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized (11.6) with the initializer.


[dcl.init]/(17.4) — If the initializer is (), the object is value-initialized.


[dcl.init]/8 To value-initialize an object of type T means:

(8.4) — otherwise, the object is zero-initialized.


[dcl.init]/6 To zero-initialize an object or reference of type T means:

(6.1) — if T is a scalar type (6.9), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T


[basic.types]/9 ... enumeration types ... are collectively called scalar types.

Put together, ALPHA() is equivalent to static_cast<ALPHA>(0)

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • I'm not sure if this answers the question "Is the default initialization/construction of enum classes defined behavior?". `ALPHA()` isn't default initialization, it's value initialization, same as `ALPHA b{}`. What would happen with `ALPHA c;`? – ctn Jul 23 '21 at 14:08
  • @ctn Uninitialized, same as, say, `int d;` – Igor Tandetnik Jul 23 '21 at 14:17
  • Thanks. Could you add a mention of this in your answer please? I think it would be appropriate given the wording of the question, but more importantly: I briefly looked and haven't found a SO question with an answer that addresses this, and other people will also run across this answer when searching for default initialization of enum classes. – ctn Jul 23 '21 at 15:25
  • 1
    @Igor Tandetnik ***ALPHA() is equivalent to static_cast(0)***. What would happen if none of the enumerators is equivalent to 0? Say `enum class ALPHA{ x=1;y=2;z=3;}` – John Mar 10 '22 at 07:19
  • 1
    @John Then you would have a value not equal to any of `x`, `y` or `z`. Nothing says that a value of enum type must always match one of the enumerators. – Igor Tandetnik Mar 10 '22 at 14:37
5

enumeration with fixed underlying type can be initialized by initializer-list if it's in the context of direct initialization and the initializer-list contains a single element with no narrowing conversion involved.

[dcl.enum]/8

[...] It is possible to define an enumeration that has values not defined by any of its enumerators.

[dcl.init]/6.1

To zero-initialize an object or reference of type T means:

(6.1) if T is a scalar type, the object is initialized to the value obtained by converting the integer literal 0 (zero) to T

That said, it's possible to have an enumeration initialized with values that is not in the range of its enumerators, but when it does fall in range, then it correspond to the enumerator.

In your example, the zero initialization initialize a and b to with 0 which correspond to the enumerator X, meaning... your example is well defined.

Community
  • 1
  • 1
Jans
  • 11,064
  • 3
  • 37
  • 45