Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum and anonymous enum in C++

Tags:

c++

1) The following code shows the index of the enum element wednesday .How can i make it to print the value instead of the index.

int main()
{
    enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
    day d=wednesday;
    cout<<d;
    return 0;
}

2) In what situation will I prefer anonymous enum over enum

like image 343
Naveen Avatar asked Jul 24 '13 10:07

Naveen


2 Answers

1). Your code prints the value of the enum, not the index. In your specific example, the index is the same as the value (by default, the first value of an enum gets the numerical value 0, and the rest get consecutive increasing values.

To check:

int main()
{
    enum day{sunday = 5,monday,tuesday,wednesday,thursday,friday,saturday};
    day d=wednesday;
    cout<<d; // will print 8 (as in 5 + 1 + 1 + 1)
    return 0;
}

If by "print the value" you meant printing "wednesday", you should do this:

enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};

std::ostream& operator << (std::ostream& out, const day d)
{
    static const char *as_strings[] = {"sunday", "monday",
        "tuesday", "wednesday", "thursday", "friday", "saturday"
    };
    return out << as_strings[static_cast<int>(d)]; // this only works 
                 // for enum values starting from 0 and being consecutive
                 // otherwise you should use a switch(d) and 
                 // print each value separately
}

int main()
{
    day d=wednesday;
    cout<<d; // will print wednesday
    return 0;
}

Edit:

2) In what situation will I prefer anonymous enum over enum

You prefer an anonymous enum when you do not need to pass it as a parameter, but need to assign meaningful names to constant numeric values:

my_object record_to_myobject(record& r)
{
    enum {id, value1, value2}; // indexes within record
    int result_id = r[id]; // much more meaningful than r[0]
    int result_value1 = r[value1];
    int result_value2 = r[value2];
    return my_object{result_id, result_value1, result_value2};
}

It's fine to use an anonymous enum here because where you pass the value as argument, you need an int, not an enum type. If you need an enum type, then you have to give it a name. Otherwise, you do not.

like image 131
utnapistim Avatar answered Oct 28 '22 11:10

utnapistim


First, the language doesn't provide any means of mapping the internal enum value to a string. It can't, really; consider:

enum Numbers {
    one = 1,
    two = 2,
    three = 3,
    un = 1,
    deux = 2,
    trois = 3
};

Once you've assigned the enum constant to an enum variable, it contains the numerical value, and nothing else. And if the numerical value in the above is 2, how can the system know whether it should map to two or to deux.

In practice, the mapping is useful in many contexts. A long time ago, I wrote a simple parser to generate the mapping code; it ignores most of C++, won't work in cases where e.g. the enum is wrapped in a macro, the code it generates won't compile if the enum is private or protected, and it's undefined which string you get in cases like the above, but I've still found it extremely useful.

For the second question: anonymous enums are usually used when the only purpose of the enum is to generate constants. Things like:

enum { maxSize = 4096 };

were widely used before you could provide the initialization constant for static member variables. And I've often found it convenient to define bit masks using an anonymous enum, even when the actual values were on some sort of unsigned type. Things like:

enum {
    offsetMask = 0xF000,
    offsetShift = 12,
    NS = 0x100,
    CWR = 0x80,
    ECE = 0x40,
    URG = 0x20,
    ACK = 0x10,
    //  ...
};
uint16_t flags;
//  ...
flags = offset << offsetShift | ACK;

I don't want to declare my variables to have an enum; they must be exactly 16 bits (according to the TCP specification). In C, I'd probably have used a #define, and in modern C++, I might use static uint16_t const member variables, but through out most of my C++ career, something like the above would have been the normal solution.

like image 38
James Kanze Avatar answered Oct 28 '22 11:10

James Kanze