Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isocpp allows us to exceed enum class values?

I found out a planty of interesting things when I programming, and one of they is:

enum class Foo {
  FOO_THING,
  FOO_TOO
};

int main() {
  Foo foo {'d'};    // It is OK
  Foo foo2 {3};    // and that one too
}

Debugger says that its value is:

foo:  (unknown: 100)
foo2: (Foo::FOO_TOO | unknown: 2)

Could you tell me, why it is allowed to initialize Foo with values that exceed declared enum class values?

Compiler version and command:

Compiler GCC (g++ (Ubuntu 7.3.0-21ubuntu1~16.04) 7.3.0)
$ g++ -Wall -std=c++17 foo.cpp

I really want to know a reason of creating that initialization mechanism in C++17?

As far as I know enum class is created, to not allow users to use enums in that way.

like image 450
BartekPL Avatar asked Jun 08 '26 17:06

BartekPL


2 Answers

Could you tell me, why it is allowed to initialize Foo with values that exceed declared enum class values?

As one of other answers says - enums are integers under the hood. It is implementation-specific which integral type is used for specific enum. That is why You can assign integer to enum.

As far as I know enum class is created, to not allow users to use enums in that way.

This is actually untrue - enum class exists to be unable to implicitly cast enum TO integer, not the other way. Notice that implicit casting of int to clas enum does not pose much possible threat.

Note that explicit casts are perfectly valid and sometimes useful.

Enums as bit flags

Sometimes enums can be used as bit flags

enum class O{
    NOTHING = 0,
    VERBOSE = 1,
    QUIET = 2,
    LOG = 4
};

Now imagine You want to pass Your options, but You want Your output to be logged and verbose. So You should pass 4 | 1 = 5. This exceeds the enum value. For me it is only valid (to some extent, there are better solutions to this problem) usage of class enum exceeding the max value.

like image 192
bartop Avatar answered Jun 10 '26 07:06

bartop


Every enum class has an underlying type, which must be at least one byte big. Any single-character constant like 'd' fits in a byte.

( C++ defines a byte as the amount of storage for one character. 8 bits are called an "octet" in C++ jargon)

Note that for "old" enums, the range is defined more restrictively, but that affects the conversion rules. You still have an underlying type, and that still has to be one byte big.

like image 45
MSalters Avatar answered Jun 10 '26 07:06

MSalters