How to use enums in C++

C++Enums

C++ Problem Overview


Suppose we have an enum like the following:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};

I want to create an instance of this enum and initialize it with a proper value, so I do:

Days day = Days.Saturday;

Now I want to check my variable or instance with an existing enum value, so I do:

if (day == Days.Saturday)
{
    std::cout << "Ok its Saturday";
}

Which gives me a compilation error:

> error: expected primary-expression before ‘.’ token

So to be clear, what is the difference between saying:

if (day == Days.Saturday) // Causes compilation error

and

if (day == Saturday)

?

What do these two actually refer to, in that one is OK and one causes a compilation error?

C++ Solutions


Solution 1 - C++

This code is wrong:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days.Saturday;
if (day == Days.Saturday)

Because Days is not a scope, nor object. It is a type. And Types themselves don't have members. What you wrote is the equivalent to std::string.clear. std::string is a type, so you can't use . on it. You use . on an instance of a class.

Unfortunately, enums are magical and so the analogy stops there. Because with a class, you can do std::string::clear to get a pointer to the member function, but in C++03, Days::Sunday is invalid. (Which is sad). This is because C++ is (somewhat) backwards compatable with C, and C had no namespaces, so enumerations had to be in the global namespace. So the syntax is simply:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday)

Fortunately, Mike Seymour observes that this has been addressed in C++11. Change enum to enum class and it gets its own scope; so Days::Sunday is not only valid, but is the only way to access Sunday. Happy days!

Solution 2 - C++

This will be sufficient to declare your enum variable and compare it:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Saturday;
if (day == Saturday) {
    std::cout << "Ok its Saturday";
}

Solution 3 - C++

Much of this should give you compilation errors.

// note the lower case enum keyword
enum Days { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };

Now, Saturday, Sunday, etc. can be used as top-level bare constants,and Days can be used as a type:

Days day = Saturday;   // Days.Saturday is an error

And similarly later, to test:

if (day == Saturday)
    // ...

These enum values are like bare constants - they're un-scoped - with a little extra help from the compiler: (unless you're using C++11 enum classes) they aren't encapsulated like object or structure members for instance, and you can't refer to them as members of Days.

You'll have what you're looking for with C++11, which introduces an enum class:

enum class Days
{
    SUNDAY,
    MONDAY,
    // ... etc.
}

// ...

if (day == Days::SUNDAY)
    // ...

Note that this C++ is a little different from C in a couple of ways, one is that C requires the use of the enum keyword when declaring a variable:

// day declaration in C:
enum Days day = Saturday;

Solution 4 - C++

You can use a trick to use scopes as you wish, just declare enum in such way:

struct Days 
{
   enum type
   {
      Saturday,Sunday,Tuesday,Wednesday,Thursday,Friday
   };
};

Days::type day = Days::Saturday;
if (day == Days::Saturday)

Solution 5 - C++

Rather than using a bunch of if-statements, enums lend themselves well to switch statements

I use some enum/switch combinations in the level builder I am building for my game.

EDIT: Another thing, I see you want syntax similar to;

if(day == Days.Saturday)
etc

You can do this in C++:

if(day == Days::Saturday)
etc

Here is a very simple example:

EnumAppState.h

#ifndef ENUMAPPSTATE_H
#define ENUMAPPSTATE_H
enum eAppState
{
	STARTUP,
	EDIT,
	ZONECREATION,
	SHUTDOWN,
	NOCHANGE
};
#endif

Somefile.cpp

#include "EnumAppState.h"
eAppState state = eAppState::STARTUP;
switch(state)
{
case STARTUP:
	//Do stuff
	break;
case EDIT:
	//Do stuff
	break;
case ZONECREATION:
	//Do stuff
	break;
case SHUTDOWN:
	//Do stuff
	break;
case NOCHANGE:
	//Do stuff
	break;
}

Solution 6 - C++

You are looking for strongly typed enumerations, a feature available in the C++11 standard. It turns enumerations into classes with scope values.

Using your own code example, it is:

  enum class Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
  Days day = Days::Saturday;

  if (day == Days::Saturday)  {
    cout << " Today is Saturday !" << endl;
  }
  //int day2 = Days::Sunday; // Error! invalid

Using :: as accessors to enumerations will fail if targeting a C++ standard prior C++11. But some old compilers doesn't supported it, as well some IDEs just override this option, and set a old C++ std.

If you are using GCC, enable C+11 with -std=c++11 or -std=gnu11 .

Be happy!

Solution 7 - C++

If you are still using C++03 and want to use enums, you should be using enums inside a namespace. Eg:

namespace Daysofweek{
enum Days {Saturday, Sunday, Tuesday,Wednesday, Thursday, Friday};
}

You can use the enum outside the namespace like,

Daysofweek::Days day = Daysofweek::Saturday;

if (day == Daysofweek::Saturday)
{
    std::cout<<"Ok its Saturday";
}

Solution 8 - C++

This should not work in C++:

Days.Saturday

Days is not a scope or object that contains members you can access with the dot operator. This syntax is just a C#-ism and is not legal in C++.

Microsoft has long maintained a C++ extension that allows you to access the identifiers using the scope operator:

enum E { A, B, C };

A;
E::B; // works with Microsoft's extension

But this is non-standard before C++11. In C++03 the identifiers declared in an enum exist only in the same scope as the enum type itself.

A;
E::B; // error in C++03

C++11 makes it legal to qualify enum identifiers with the enum name, and also introduces enum classes, which create a new scope for the identifiers instead of placing them in the surrounding scope.

A;
E::B; // legal in C++11

enum class F { A, B, C };

A; // error
F::B;

Solution 9 - C++

Sadly, elements of the enum are 'global'. You access them by doing day = Saturday. That means that you cannot have enum A { a, b } ; and enum B { b, a } ; for they are in conflict.

Solution 10 - C++

While C++ (excluding C++11) has enums, the values in them are "leaked" into the global namespace.
If you don't want to have them leaked (and don't NEED to use the enum type), consider the following:

class EnumName {  
   public:   
      static int EnumVal1;  
      (more definitions)  
};  
EnumName::EnumVal1 = {value};  
if ([your value] == EnumName::EnumVal1)  ...

Solution 11 - C++

Enums in C++ are like integers masked by the names you give them, when you declare your enum-values (this is not a definition only a hint how it works).

But there are two errors in your code:

  1. Spell enum all lower case
  2. You don't need the Days. before Saturday.
  3. If this enum is declared in a class, then use if (day == YourClass::Saturday){}

Solution 12 - C++

I think your root issue is the use of . instead of ::, which will use the namespace.

Try:

enum Days {Saturday, Sunday, Tuesday, Wednesday, Thursday, Friday};
Days day = Days::Saturday;
if(Days::Saturday == day)  // I like literals before variables :)
{
    std::cout<<"Ok its Saturday";
}

Solution 13 - C++

If we want the strict type safety and scoped enum, using enum class is good in C++11.

If we had to work in C++98, we can using the advice given by InitializeSahib,San to enable the scoped enum.

If we also want the strict type safety, the follow code can implement somthing like enum.

#include <iostream>
class Color
{
public:
    static Color RED()
    {
        return Color(0);
    }
    static Color BLUE()
    {
        return Color(1);
    }
    bool operator==(const Color &rhs) const
    {
        return this->value == rhs.value;
    }
    bool operator!=(const Color &rhs) const
    {
        return !(*this == rhs);
    }

private:
    explicit Color(int value_) : value(value_) {}
    int value;
};

int main()
{
    Color color = Color::RED();
    if (color == Color::RED())
    {
        std::cout << "red" << std::endl;
    }
    return 0;
}

The code is modified from the class Month example in book Effective C++ 3rd: Item 18

Solution 14 - C++

Don't think of an enum as a group of objects, think of it as an integer where each numeric value has a name so enum Days would be better declared as enum Day. If you want to contain it within a named structure put enum Day within a struct Days like this:

struct Days{
    enum Day{
        Saturday,
        Sunday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday
    };
};

Then you would address them like this Days::Saturday and the type would be Days::Day

Solution 15 - C++

First of all, make 'E' in enum, 'e' as a lower case.

Second, drop type name 'Days' in 'Days.Saturday'.

Third ...buy yourself a good C++ book.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHosseinView Question on Stackoverflow
Solution 1 - C++Mooing DuckView Answer on Stackoverflow
Solution 2 - C++mathematician1975View Answer on Stackoverflow
Solution 3 - C++pb2qView Answer on Stackoverflow
Solution 4 - C++ataman1xView Answer on Stackoverflow
Solution 5 - C++Dean KnightView Answer on Stackoverflow
Solution 6 - C++Alex ByrthView Answer on Stackoverflow
Solution 7 - C++SanView Answer on Stackoverflow
Solution 8 - C++bames53View Answer on Stackoverflow
Solution 9 - C++GrzegorzView Answer on Stackoverflow
Solution 10 - C++InitializeSahibView Answer on Stackoverflow
Solution 11 - C++Balázs ÉdesView Answer on Stackoverflow
Solution 12 - C++James OravecView Answer on Stackoverflow
Solution 13 - C++Xu HuiView Answer on Stackoverflow
Solution 14 - C++CommanderLakeView Answer on Stackoverflow
Solution 15 - C++vikramjitSinghView Answer on Stackoverflow