Search

S.4.5a — Enum classes

Although enumerated types are distinct types in C++, they are not type safe, and in some cases will allow you to do things that don’t make sense. Consider the following case:

When C++ compares color and fruit, it implicitly converts color and fruit to integers, and compares the integers. Since color and fruit have both been set to enumerators that evaluate to value 0, this means that in the above example, color will equal fruit. This is definitely not as desired since color and fruit are from different enumerations and are not intended to be comparable! With standard enumerators, there’s no way to prevent comparing enumerators from different enumerations.

C++11 defines a new concept, the enum class (also called a scoped enumeration), which makes enumerations both strongly typed and strongly scoped. To make an enum class, we use the keyword class after the enum keyword. Here’s an example:

With normal enumerations, enumerators are placed in the same scope as the enumeration itself, so you can typically access enumerators directly (e.g. red). However, with enum classes, the strong scoping rules mean that all enumerators are considered part of the enumeration, so you have to use a scope qualifier to access the enumerator (e.g. Color::red). This helps keep name pollution and the potential for name conflicts down.

Because the enumerators are part of the enum class, there’s no need to prefix the enumerator names (e.g. it’s okay to use red instead of COLOR_red, since Color::COLOR_red is redundant).

The strong typing rules means that each enum class is considered a unique type. This means that the compiler will not implicitly compare enumerators from different enumerations. If you try to do so, the compiler will throw an error, as shown in the example above.

However, note that you can still compare enumerators from within the same enum class (since they are of the same type):

With enum classes, the compiler will no longer implicitly convert enumerator values to integers. This is mostly a good thing. However, there are occasionally cases where it is useful to be able to do so. In these cases, you can explicitly convert an enum class enumerator to an integer by using a static_cast to int:

There’s little reason to use normal enumerated types instead of enum classes.

Note that the class keyword, along with the static keyword, is one of the most overloaded keywords in the C++ language, and can have different meanings depending on context. Although enum classes use the class keyword, they aren’t considered “classes” in the traditional C++ sense. We’ll cover actual classes later.

Also, just in case you ever run into it, “enum struct” is equivalent to “enum class”. But this usage is not recommended and is not commonly used.


S.4.7 -- Structs
Index
S.4.5 -- Enumerated types

121 comments to S.4.5a — Enum classes

  • Anathbel

    Why did you define "standard enum" outside the main function, while "enum class" are defined inside main function? Is there any reason for that?

  • Anathbel

    Why do in the following code, enumerators are lower cases and are not prefixed like 'COLOR_RED'?

    • nascardriver

      Enumerators shouldn't be upper case, because they could conflict with preprocessor macros. This is currently inconsistent in the lessons.

      I added prefixes to the first example, thanks for pointing this out :) Prefix aren't necessary in `enum class`.

  • ColdCoffee

    LAST CODE GIVES FOLLOWING ERROR IN VISUAL STUDIO !!

    HelloWorld.cpp(13,23):error C2679: binary '<<': no operator found which takes a right-hand operand of type 'main::Color' (or there is no acceptable conversion)
    HelloWorld.cpp(13,23): message : while trying to match the argument list '(std::ostream, main::Color)'
    1>Done building project "HelloWorld.vcxproj" -- FAILED.

  • Thomas Kennings

    EDIT: **FIXED** but a good reference. I fixed the issue by moving my enum above my function prototypes. This makes sense because before the compiler came across the "Gender" type with no knowledge of what it was. Now when the compiler sees the prototypes, it knows that "Gender" is a type!

    ***

    Hi all,

    I'm trying out enums/enum class and I can't for the life of me figure out where I'm going wrong here. My program follows:

    I'm getting a "cannot overload functions distinguished by return type alone" on my prototype of the getGenderInput function. I have no idea why. I'm also getting a bunch of other compile errors (syntax) that don't make any sense. Stuff like missing ")", "}" and ";". Can anyone please help me? I've exhausted stack overflow and such to no avail.

  • salah

    Hi,
    why we can't print enum class variable directly  whereas we can compare them using if statement ??
    I mean wouldn't the compiler convert enum class variable into interger when using it in if statement ??

    • Alex

      It's intentional behavior to prevent inadvertent conversions to integers where it doesn't make sense. If you want that behavior, you can still have it, you just have to do it explicitly (via a static_cast)

  • BuIlDaLiBlE

    Absolutely not important but in the first code block there is an additional new line after the include directive, however in the other code blocks there isn't.

  • hellmet

    In 8.15 (specifically, this comment https://www.learncpp.com/cpp-tutorial/8-15-nested-types-in-classes/#comment-337755),
    I see

    I'm not sure how that works, but perhaps worth mentioning here.

  • MisterNotMister

    Hi, what happens if you are using a struct or class
    and you define an enum inside it like as such.

    (dumb example, but is this also a right way of using enums?)
    EDIT: Why aren't code tags working for me???

    • That's perfectly fine. The only problem is that nested types can't be forward declared, which can quickly lead to circular dependencies. If the nested type is used by name outside of the class, don't declare it inside the class. If the nested type is only used internally or by returns, you can declare it inside of the class.

      > Why aren't code tags working for me?
      They stop working after editing a comment. They start working again when you refresh the page.

  • YB

    In C# there is ToString() for the enum values to get the name of the value in string format.

    Is there any plan to add the same functionality for C++ enum class?
    Are there any suggestions on how to achieve the functionality with what is currently available?

    • > Is there any plan to add the same functionality for C++ enum class?
      No

      > Are there any suggestions on how to achieve the functionality with what is currently available?
      You'll have to wait until arrays or containers have been covered. After chapter 6, you can use an array or `std::map` to map enumerators to strings.

      EDIT: You could use if-statements to check for all enumerators and return the corresponding name.

  • Q

    Enum classes seem like an utterly pointless addition. Instead of bending over backwards to disallow nonsensical comparisons, why not just trust programmers not to be idiots?

  • Pharap

    I've recently been reading the isocpp style guidelines and they advise against using ALL_CAPS for enumerators.

    http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Renum-caps

    Would the author(s) of the article consider possibly adopting some of the recommendations of this guide?
    In particular, not using all-caps for enumerators.

    This article is quite popular, so if it sets a good example then it will be responsible for future C++ programmers following good guidelines, which I think can only be a good thing.

  • Puya

    Hi, thanks as always for your helpful tutorials. Is this a typo "(e.g. it’s okay to use RED instead of COLOR_RED, since Color::COLOR_RED is redundant)"? Should it be "(e.g. it’s okay to use RED instead of Color::RED, since Color::RED is redundant)"?

  • B_H@cker

    В чем отличие "emun" от "class enum"?

  • Alaa Mahran

    Can you please elaborate more about this line: "If you’re using a C++11 compiler, there’s little reason to use normal enumerated types instead of enum classes.", I missed your point here! What is the relation between C++11 and enum classes and why it would be preferable in older versions but not in C++11?

  • Yaroslav

    Hello. may be i missed it somewhere.

  • C.E

    Alex, when  you mention strong typing rules, what do you exactly mean, from my research these  "rules" govern variable assignment and implicit type conversion. Reprhasing the question would be how these specefic rules function if I am using non-class based enumerators. In addition you speak of  the keyword class being overloaded(in what sense)

    • Alex

      "strong typing" in the context of an enum class means the enumerators live inside the scope of the type (rather than in the global scope) and thus must be prefixed by the type name to be accessible.

      The keyword class is more often used for creating user defined structs that have behaviors attached. Essentially the entirety of chapter 8 is about this.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]