260

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?

7
  • 5
    i know, i want o know why its giving me the error! Commented Aug 29, 2012 at 17:04
  • 1
    Its Wednesday here. You have too lot of syntax errors for C++ compiler. Starting from 'Enum'. Commented Aug 29, 2012 at 17:06
  • 1
    @Hossein, Because enums aren't the same syntax (and semantics) in both languages. The first thing I do after getting an error when trying to use a feature in a new language is look up the syntax (or if it's possible) in that language. Commented Aug 29, 2012 at 17:08
  • @chris:I know , i do the same exact thing.hopefully i got my answer.I also updated the question to be more clearer.Thank you by the way;) Commented Aug 29, 2012 at 17:11
  • 18
    "as far as i know the enums declaration and usage in these two languages are the same.". There's your problem, right there. C# is not the same language as C++. Particularly, they have different syntax for enums. Commented Aug 29, 2012 at 17:26

15 Answers 15

406

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!

Sign up to request clarification or add additional context in comments.

7 Comments

Fortunately, your complaint 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!
Gotta love the C++ error messages...they prove that the language is to cumbersome to even give good feedback. I take it a 'primary-expression' is an object or a scope or some other thing that is NOT a type. Perhaps a Type is a 'secondary-expression'. And what a C++ developer might call a 'dot operator' the C++ compiler can only call a 'token'. When it gets that hard to understand the error messages there is something wrong with the language I think.
@Travis: en.cppreference.com/w/cpp/language/…. A primary expression is just the first thing in an expression, usually a name or variable or a literal. As for the second part, I don't see a big difference between '.' token and dot operator, other than it's a token and not an operator, and it shows the exact symbol, rather than a name.
@Mike Seymour I've tried to access the enums without the scope resolution operators on a bunch of compilers, and it seems to work. You said as of C++11 it's the only way, for some reason I can just access the enum values as globals, don't need the ::
@TitoneMaurice: If you have an enum, you can use no scope, or the global scope (::Saturday). If you have an enum class (which is a very different thing), then you have to use Days::Saturday.
|
31

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; 

1 Comment

I have updated the question,I think its now clearer what i'm exactly after:) By the way thankyou:)
26

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"; } 

5 Comments

why is it wrong to say if ( day== Days.Satudday) ? they must be the same,so why is compiler complaining about it?
@Hossein the values declared in your enum do not behave like class or struct member variables. This is not the correct syntax to use
@Hossein: because Days is not a scope, nor object. It is a type. And Types themselves don't have members. std::string.clear also fails to compile for the same reason.
@Hossein: Because that's not how enums in C++ work. Unscoped enumerations put their values into the surrounding namespace; scoped ones (enum class, new in 2011) have their own scope, and are accessed using the scope operator, Days::Saturday. The member access operator (.) is only used to access class members.
@MooingDUck and MikeSeymour Would one of you guys post your answer as an answer? because that is exactly what i was after by issuing this question ;)
19

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) 

Comments

15

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 .

Comments

12

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; } 

4 Comments

The nice thing here is that compilers will tell you if you missed putting a case in.
Shouldnt you use class enum in this case?
enum is just a datatype in C++ So declaring an enum like I did above in a .h file, and then including that file in whatever .cpp file you want to use it in will give you access to the enum. Just noticed I forgot to add the #include in my .cpp example. Editing.
Also, I see someone else saying that enums in C++ are global. In my experience, using enums the way I have above, I can only access them when I have included the .h. So this seems to stop global access too, which is always good. EDIT: It seems like I am unknowingly using enums in a C++11 way if I am reading things right...
10

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"; } 

Comments

7

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; 

Comments

5

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.

6 Comments

Until you use enum class in C++11, that is. Before that, you have to make dummy classes.
Don't know C++11. I am assuming the question refers to C++. Yes, using classes or namespaces will do the trick.
@Grzegorz: i think chris is referring to the newly introduced enum class which provides strongly typed enums.
@Hossein: Thank you for pointing it out. I have found explanation of the num class, and I know what Chris was talking about. Thanks a lot.
@Grzegorz:I didn't mean to disrespect,just thought i might be helping,sorry for any probable misunderstanding.I again Thank you for your time and helping me ;)
|
4

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) ... 

Comments

3

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){}

1 Comment

The OP changed the spelling/case 16 minutes after the initial post (revision 1 to revision 2).
1

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"; } 

3 Comments

This does not work: to use the Days:: scope as in your example, you must define the enumeration with enum class Days and use C++03+Microsoft extension or C++11.
@Futal, the above ran with Borland C++ Builder. Flavor / Version of C++ is not in the question.
your version of Borland C++ Builder must be using C++11 or newer. Gcc and Clang both gives errors or warnings if your example is compiled with -std=c++98 or -std=c++03. Clang is quite clear: warning: use of enumeration in a nested name specifier is a C++11 extension.
1

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

Comments

0

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

Comments

-15

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.

1 Comment

Sorry you got all these down-votes (I mean, the answer does kind of deserve it), but that doesn't mean you have to leave the community for 6 years. Come back and join us. You have something to contribute too. Be helpful. Share knowledge.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.