62

When we have,

struct E { enum E_ { HELLO }; }; // 'E' is inheritable

then why do we need,

enum class E { HELLO };  // 'E' is not inheritable

IMO 2nd version doesn't offer more features than the 1st. I don't think that enum class is introduced just to save 2 curly braces {};! Am I missing any important aspect ?

As a minor question, is there any difference between enum class and enum struct other than syntax (because both have public access specifier) ?

James McNellis
  • 348,265
  • 75
  • 913
  • 977
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 1
    How do you reference the type of the enum inside `E` in your first example? – zneak Aug 04 '11 at 04:04
  • 4
    You might be interested in reading [this](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf) then. – zneak Aug 04 '11 at 05:48
  • 9
    plain enums are **not type-safe**, have an **implementation-defined underlying type**, **not strongly scoped** http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf – yuan Dec 08 '13 at 08:27
  • @zneak: you could add `typedef E::E_ EnumType;` – gentooise Jan 09 '20 at 11:08

5 Answers5

127

Besides what was already mentioned, an advantage of enum class is better type safety - the enum class enumerators don't convert implicitly to integers.

Kos
  • 70,399
  • 25
  • 169
  • 233
  • 1
    BTW, is there in existing C++, or will there exist in the new version, a nice way to specify that a variable should have an enum type upon which bitwise operators should be usable? The only approaches I've found are to either declare the variable to be an "int" (just using the enum to name the values) or else explicitly define all the operators which are supposed to work on the enum. The fact that such operators don't work on enums by default seems like one of the larger 'breaking' changes going from C to C++. – supercat Nov 20 '11 at 19:22
  • @supercat , probably this restriction was applied because a value of enumeration type is intuitively expected to have the value equal to one of its enumerators (and a bitwise combination of enumerators doesn't fit). So the moment you convert an enumerator to an integer (in order to do bitwise ops, for instance), it's actually no longer an enum. – Kos Nov 21 '11 at 11:15
  • @Kos: That is indeed the concept, but there are many situations where one has a variable/field whose logical meaning is to be a bitwise combination of particular flag constants. One could declare such a variable/field as an integer, but in C it would certainly be more idiomatic to declare it as an enum so as to show the relation between the variable/field and the flags constants. Given that C++ was supposed to be largely compatible with C, I find it odd that such an idiomatic usage would be disallowed. – supercat Nov 21 '11 at 15:48
  • @supercat http://stackoverflow.com/questions/13385744/how-to-make-a-enum-with-values-over-max-int-allowed/13385880#13385880 Also look at the comments where we talk about that problem and how to fix it using strong types – David Stone Dec 23 '12 at 15:48
  • 1
    @DavidStone: I do a lot of work with embedded systems and code that has to interact with them. As such, using different integral constants to represent bit masks offers at least two nice advantages compared with enums: (1) code written using such techniques works identically in C and C++; (2) it's easy to serialize and deserialize such data. In C versions with anonymous unions, using a bitfield union'ed with a byte would be a nice alternative; not sure if C++ supports that, though. – supercat Dec 23 '12 at 17:13
95

Do we really need “enum class” in C++0x?

No, we don't "need" enum class. We can get sufficiently equivalent functionality in other ways. But by that logic, we don't "need" a lot of stuff in C++. We don't "need" virtual functions and inheritance, since we can just implement it manually with vtables and such. We don't "need" member functions; these can be emulated by having them take an additional argument.

Language features exist to make programmers lives easier. Just because something can be done manually doesn't mean that it should.

enum class has the following properties:

  1. It is easy to understand; it mirrors how enums work in other languages.
  2. It requires relatively little from compiler writers. Contrast the implementation effort with features like r-value references, varadic templates, or user-defined literals.
  3. It doesn't break the syntax in any way. It may look a bit weird at first to see enum class, but that's true for most new features. Once you get used to it, it's fine.
  4. It is 100% backwards compatible, in that it doesn't redefine how regular enums work. Old-style enums work the same as they used to.
  5. It keeps you from having to write a lot of boilerplate code. Boost has a macro to create the effect of enum class definitions. Without this macro, you have to spend quite a bit of effort getting all of the corner cases to work. And even so, someone had to write and debug that macro.

So no, we do not "need" them. But they're still a great addition to the language.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 12
    Bravo, This also applies to every improvement in any area of any field. – rfcoder89 Feb 01 '13 at 12:40
  • 4
    +1. To make the point even more obvious: "You also don't **need** to wear pants, but your life is likely to be much harder if you don't." – ereOn Jan 18 '14 at 09:54
  • just about point 4. (good old enums) this is true, but one extension has been made: enumerators are now accessible through scoped (qualified) syntax. because I quote "it enables programmers to write enum-agnostic code that operates on both kinds of enums". – v.oddou May 15 '15 at 01:34
24

In the first case, the type of HELLO is not E, whereas in the second case, the type of HELLO is E.

For a good demonstration of why this is important, see Howard Hinnant's answer to "“enum class” emulation or solid alternative for MSVC 10.0."

enum class and enum struct are "semantically equivalent" (i.e., the same), per C++0x FDIS §7.2/2.

Community
  • 1
  • 1
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • I read the answer. That problem could have been easily fixed by overloading `operator ostream` with `my_enum::type`; http://www.ideone.com/hvgk4. This is just a minor change, which `enum class` would have provided readily. But still is it worth ? – iammilind Aug 04 '11 at 04:13
  • 4
    Yes, it's definitely still worth it: it's a small, self-contained addition to the language that enables cleaner use of enumerations and replaces a number of kludges (many of which are incorrect). It's not game changing like rvalue references, lambda expressions, or variadic templates, but that doesn't mean it's not a useful feature. – James McNellis Aug 04 '11 at 04:47
  • 1
    "That problem could have been easily fixed" ... but... at the cost of making a compile-time constant a member variable (plus, although insignificant, having to maintain an address for the struct -- even if all data is constant or there is no data at all, the compiler must still be prepared that you try to take the struct's address, it cannot know for sure that you won't). – Damon Aug 04 '11 at 09:33
16

I think you need to read in the other advantages of these new enums

  • user defined size
  • scoped values (no more general scope cramming of values)
  • no implicit conversion to integral types
  • forward declaration of enums (biggest improvement for enums in APIs)

http://www.stroustrup.com/C++11FAQ.html#enum

rkhb
  • 14,159
  • 7
  • 32
  • 60
David
  • 3,324
  • 2
  • 27
  • 31
1

Yes, we do. Looks like no one pointed out this before. What about if you need to set size of an enum and keep still according to C++ standard? enum class can do. And with type safety as already mentioned. It's reduce so much possible bugs in code and the mess to mixing int and enums. They wasn't never the same thing for me. Amazing. e.g., enum class foo : int16_t { ... } I'm sure each member is an int16_t and not up to implementation decide what's "better" for me.

EDIT:

Also, we can have duplicated values (not names) in the list. Which make a lot of sense depending to context.

The Mask
  • 17,007
  • 37
  • 111
  • 185