5

I've witnessed today a form of enum that was written as such, compiled under VS 2017:

enum ens en1, en2, en3;

and then it was used as such:

int n = en2;

So my question is, what form of enum was it and why n was later set to 0?


Live example:

enum ens en1, en2, en3;

int main()
{
    int n = en2;
}

compiles without warning with the default compiler options

François Andrieux
  • 28,148
  • 6
  • 56
  • 87
c00000fd
  • 20,994
  • 29
  • 177
  • 400

3 Answers3

3

This example is not correct because declaration of enum must either include underlaying type or a list of items. This also means that it can not be combined with variable declaration. fixed variant:

enum ens: int; // ens is a complete type at this point
enum ens en1, en2, en3; // en1 en2 en3 are global variables of enum ens type

// alternative "traditional" enum definition with empty list of items:
enum ens{} en1, en2, en3;

int n = en2; makes n equal to 0 because en2 is a global variable and is implicitly initialized with 0.

user7860670
  • 35,849
  • 4
  • 58
  • 84
  • You know, it's interesting because VS2017 also compiles it with this: `enum ens en1, en2, en3 {};` – c00000fd Nov 05 '18 at 20:27
  • 1
    @c00000fd `en3 {}` is a variable initialization, it can also be `enum ens{} en1{}, en2{}, en3{};` - same thing – user7860670 Nov 05 '18 at 20:28
  • Of what type? a function. – c00000fd Nov 05 '18 at 20:32
  • @c00000fd of `enum ens` type – user7860670 Nov 05 '18 at 20:33
  • So what can you put into those curly braces? (Except `ens{}`, which is a list declaration.) – c00000fd Nov 05 '18 at 20:34
  • @c00000fd **10.2 Enumeration declarations [dcl.enum]** *"If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a single enumerator with value 0."* So you can put either nothing or 0 – user7860670 Nov 05 '18 at 20:35
  • No, not the `ens{}`, I get that one. I'm talking about `en1{}`, `en2{}` and `en3{}`. What would you normally put into those curly braces if those are variable declarations? – c00000fd Nov 05 '18 at 20:37
  • 1
    @c00000fd `en1{}` is a [list-initialization syntax](https://en.cppreference.com/w/cpp/language/list_initialization). So you normally put initial value inside or nothing. So in this case since `enum ens` can only hold 0 we can write either `en1{}` or `en1{static_cast(0)}` – user7860670 Nov 05 '18 at 20:38
  • Oh, OK. I see now. So you can technically turn it into this: `enum ens { v, v1, v2} en1{(ens)10}, en2{(ens)4}, en3 {(ens)8};` Wow. – c00000fd Nov 05 '18 at 20:41
  • @c00000fd Nope, `(ens)8` will be invalid because it will be definitely outside of unscoped enumerator range – user7860670 Nov 05 '18 at 20:42
1
enum ens en1, en2, en3;

is no enum declaration. It is a variable declaration. It declares 3 variables of type enum ens. They are used in the code later.

At the assignment of

int n = en2;

the value of en2 happens to have an enum value that corresponds to the integer value 0.

Marcel
  • 1,688
  • 1
  • 14
  • 25
  • 1
    `ens` hasn't been defined yet so how are you declaring variables with its type? – NathanOliver Nov 05 '18 at 20:19
  • @NathanOliver The question doesn't show a MCVE, just a single line of code. So `ens` might be defined. It does state that the code compiled, so it's a reasonable assumption. Edit : I mean it might not have been meant as a MCVE. – François Andrieux Nov 05 '18 at 20:25
  • @FrançoisAndrieux I'll update the Q. The MCVE [Here](https://godbolt.org/z/pOISuY) works just fine and it shouldn't – NathanOliver Nov 05 '18 at 20:28
1

This is non-conforming code, it is an extension as we can see if we use /Za MSVC also rejects the code.

We can see this is ill-formed from dcl.enum#2:

The enumeration type declared with an enum-key of only enum is an unscoped enumeration, and its enumerators are unscoped enumerators. The enum-keys enum class and enum struct are semantically equivalent; an enumeration type declared with one of these is a scoped enumeration, and its enumerators are scoped enumerators. The optional identifier shall not be omitted in the declaration of a scoped enumeration. The type-specifier-seq of an enum-base shall name an integral type; any cv-qualification is ignored. An opaque-enum-declaration declaring an unscoped enumeration shall not omit the enum-base. ...

This wording was added n2764 which allowed forward declaration of enums as long as the underlying type was specified.

For more details as to why we are not allowed to forward declare enums without an underlying type see Why must an enumeration's size be provided when it is forward declared?

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740