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:

If you’re using a C++11 compiler, there’s really no 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.

4.6 -- Typedefs and type aliases
4.5 -- Enumerated types

47 comments to 4.5a — Enum classes

  • Joseph

    Hi, I’m using the CodeBlocks that I downloaded a couple weeks ago, and it’s saying that the class ‘color’ doesnt exist. I tried to make my own and when it failed, i copy pasted your code to see if it was me or the compiler, and yours failed too. How can I fix this?

    • Alex

      I’m guessing your compiler either isn’t C++11 compliant, or has C++11 functionality turned off.

      I found this bit of advice on the web: “In code::blocks, go to project->build options->compiler settings->compiler flags and check “Have G++ follow C++11 ISO standard”

      Try that, and let me know if it works so I can update the tutorials.

  • There seems to be another difference in using enum and enum class (at least in C++11):

    And also this:

    • And furthermore this:

      Why? => Because strongly typed enums won’t convert to integers implicitly !
      So you need to use static_cast. I thought of that in the first place but I seemed to have made it incorrectly … so I thought, there must be another problem/difference. Now that’s sorted. However, this seems to make enum classes less convenient in a way.

      If you’re using a C++11 compiler, there’s really no reason to use normal enumerated types instead of enum classes.

      Well, one reason would be, if you’re tired of type casting.

  • Connor

    Hello Alex.
    First - thank you so much for this tutorial. It is absolutely EPIC!

    WRT Josephs comment, I to was experiencing the same error on code::blocks. However, when I changed the compiler flags to “Have G++ follow C++11 ISO standard" it still won’t compile but changes the error:

    cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’.

    do you know if thee is a solution to this?
    Thanks again.

    • Alex

      Sorry Connor, I’m afraid this is beyond my knowledge. I’d definitely turn to the almighty Google for help on this one.

      Try searching for “code::blocks cannot bind ‘std::basic_ostream’ lvalue to ‘std::basic_ostream&&’.” and see if you get any hits. Surely someone else has run into (and resolved) this issue before.

      • Chris

        I’ve been getting this as well. It seems to happen when I try to output an enum member(correct terminology?) directly as an integer. EG:

        Btw, thanks a million for this tutorial. It’s pretty much the new gold standard haha.

        • Alex

          Oh, I see what’s happening now that you’ve provided some context. With an enum class, the compiler won’t do an implicit conversion from an enum class to an integer.

          All you need to do is use static_cast to cast your enum class variable (color) to an integer:

    • Jim

      Hey Conner,
      Your post is pretty old but if you clicked the box to use C++ 11 ISO it should cover all the new changes.

      Where did you come up with this code cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&
      did you check it for typos?  What is it supposed to do?

  • Todd


    "(eg. Color::RED)" (you’re missing a period between ‘e’ and ‘g’)

  • C++ newbie

    My code is not working.  I’m wondering if you can help me? I’ve deleted out some portions of code that I don’t think pertain to the problem.




    Compiler error: error C2664: ‘void printFruit(Fruit)’ : cannot convert argument 1 from ‘main::Fruit’ to ‘Fruit’

    Compiler error: IntelliSense: argument of type "Fruit" is incompatible with parameter of type "Fruit"

    • Alex

      Try moving enum class Fruit and Vegetable outside of function main().

      • C++ newbie

        Actually just entirely deleting the enum class Fruit from main fixed it.  What was wrong?  Was it that I declared the enum class twice because I had one in main, and one that i #included?

        • Alex

          I think because you declared Fruit inside of main, the version inside main hid the other version. Then when you tried to pass the version inside main to printFruit(), it tried to do a conversion from the Fruit inside of main to the other Fruit, and didn’t know how (despite the fact that they’re identical).

          • C++ newbie

            Dang, that’s complex.  I’ve really been enjoying your support & the tutorial overall, though.  Thanks. (although I probably won’t be using enums in my simple code!  structs seem cool though..)

  • R4Z3R

    How I can find out that my Compiler supports C++11 or not?

  • The Razer

    Can you suggest me a good IDE that supports c++11 ? (except visual studio)

  • Anthony

    Do enum classes support using directives like namespaces do?

    For example, is there code similar to this that would work:

  • Jim

    Wait, how do the two enumerations Color and Fruit in the first example above get a value? In the last lesson you said values were assigned auto. to the elements in each enumeration but not the enumerations?  I see that there is a error in the code… if color == fruit) that may have something to do with it.

    Even if you could do this comparison don’t the enum’s., have to start with capital letter? (Color & Fruit)

    When you say "placed in the same namespace" in the first sentence just after the second code it’s easy to confuse this with the keyword. Area might be better word there.
    LOL, no I’m not another Todd, it’s that using keywords in descriptions can lead us new-bee’s astray.

    • Alex

      Color and Fruit are enums declarations, so they don’t have values themselves. They just specify what the enum looks like. The enumerators within those enumerations get mapped to a value. Since no explicit values have been assigned, the C++ compiler assigns values to the enumerators starting from 0 in sequential order (RED = 0, BLUE = 1, BANANA = 0, APPLE = 1).

      color and fruit are variables of the enum type Color and Fruit respectively. These work just like normal variables, and they can be assigned to, compared, etc… You can’t compare Color and Fruit because they’re just declarations (it would be like comparing int and float -- what does that even mean?).

      > When you say “placed in the same namespace” in the first sentence just after the second code it’s easy to confuse this with the keyword.

      I used the word “namespace” deliberately, but I’ve updated the article to talk about scopes instead of namespaces. With an enum class, the enumerator is defined inside the scope of the enumeration itself (which is why you have to use a scoping prefix to access it).

  • Jim

    I’ve forgotten to provide an answer to the math above when I post quite a few comments. Then I loose all of the time and wording I’ve written.  Do you think someone can fix this to send us back to Leave a comment?

  • Jim

    For the third time (see above) I apologize if my earlier post was in error. I guess I’m a bit confused about namespace
    in the first code above your comment said enum Color and RED // RED is placed in the same namespace as Color.
    Then in the second your comment said enum class Color and RED, // RED is considered part of Color, not as part of the namespace that Color is in.

    I think of Color as a(custom)type,and Red as one of Color’s elements. I can’t imagine how they can be in the same namespace in the enum Color and not in the enum Class Color.

    Please clarify Thank You

    • Alex

      This is a hard concept to explain, so let me try again.

      Consider the following snippet of code:

      You’ll agree that enum b is inside of namespace a, right? So we’d access it as a::b. With a normal enum, c and d are both also inside of a, so we’d access them as a::c and a::d. This is what I mean by the enumerators are in the same namespace as the enumeration.

      Now change the enum to an enum class. In this case, the enumeration is accessed via a::b. However, the enumerators are accessed as a::b::c or a::b::d.

      Note that the enumerators and the enumerations are no longer at the same level. The enumerators are inside the namespace of the enumeration.

      Now remove namespace a, and that’s your normal case. In the normal enum case, b and c and d can be accessed directly. In the enum class case, b can be accessed directly, but c and d are still accessed as b::c and b::d.

      Make sense?

  • ak

    I am not able to understand that why we are not using .h with the iostream ?

  • There seems to be a problem which i cannot understand while trying to compile this code with the codeblocks(13.12). It says Fruit is not a class or a namespace.

  • Lokesh

    It is written "When C++ compares color and fruit, it implicitly converts color to fruit to integers, and compares the integers."
    Is color converted to type fruit or both color and fruit are converted to integers?
    If the latter case is true, it should be
    "… it implicitly converts color and fruit to integers, …"

  • Manoj

    Can the enum items be accessed by index?
    Ex. cout << Color(1) << endl;

    • Alex

      What you’re actually doing here is a C-style cast on integer 1, and casting it to an object of type Color. So you’re not accessing it, you’re converting it.

  • Ciccio

    I think that another important advantage of enum classes is that you can specify the underlying integer type:

    • Alex

      Thanks for teaching me something new! 🙂

      • Raquib


        Are you talking about the integer assigned to the enumerators???
        Makes sense when you have more than 2^32 enumerators int will no longer work.

        Another validation needed is- when we talk about global namespace, its just a concept right, kind of like the universal set, where enum class is a subset like namespace std is………. and there isn’t any specific namespace named global (namespace global{….; …; }), of course there ain’t one, else we would have accessed any global variable in it as "global::identifier" and not as  "::identifier", the blank signifies it being global.


        • Alex

          Yes, though I’ve never seen an enumeration with more than 255 enumerators, let alone 2^32.

          The global namespace is essentially the “outermost” namespace. It can contain inner namespaces (defined using enum classes, the namespace keyword, etc…). As you say, using the scope resolution operator with no prefix means the global namespace.

  • Alfred O.

    I’m having a heck of a time trying to forward declare an enum. I downloaded the community version of Visual Studio (from 2015) to get a more up-to-date compiler, and despite what the book "C++ Primer" says about being able to forward declare an enum, I can’t get it to work for me. According to that book, it should be as simple as typing:

    enum class Color : unsigned char;

    Into a header file and defining the enum somewhere else, like Color.cpp:

    enum class Color : unsigned char

    But it simply won’t work. You may be able to declare an object of type Color, but you cannot initialize it or do much of anything, actually. I could figure out how to forward declare a class type, but not an enum? What madness is this?

    • Alex

      Forward declaring enums works like forward declaring any other type: the forward declaration tells the compiler that the type exists, but you can’t actually do anything with it until you define it.

  • Kılıçarslan

    Hi,Alex! I’m in a trouble understanding this.

    This code works.

    But this doesn’t.

    Even though FIRST is an integer,I can’t print it with cout<<.If I don’t use enum classes,it simply works with cout<<FIRST; I know variables of enum class can’t get implicitly assigned but I assign them explicitly.Can you find a solution why this doesn’t work?

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter