6

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

Naveen
  • 7,944
  • 12
  • 78
  • 165

7 Answers7

8

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.

utnapistim
  • 26,809
  • 3
  • 46
  • 82
  • So if I have to make a comparison then I should do it like `if(d==8)` instead of `if(d==wednesday)`? – Naveen Jul 24 '13 at 11:03
  • 1
    With enums, you should never use their integer values explicitly. Basically, you should always use `if(d == wednesday)`. This will allow you to change the enum value, without going through code and changing it to match (`day d=wednesday; if(d == wednesday)` will allways evaluate to true, no matter the value of wednesday in the enum). – utnapistim Jul 24 '13 at 11:06
  • Thanks for your effort.It helped me a lot.Can You help with the cecond part. – Naveen Jul 24 '13 at 11:12
3

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.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

You have to manually maintain an array of string "descriptions" of the enum values, which is tedious and error-prone:

static const char *daydescs[] = {
    "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"
};

int main()
{
    enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
    day d=wednesday;
    cout<< daydescs[(unsigned)d];
    return 0;
}
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
0

An enum is a number, the string representation (e.g. wednesday) is a compile time representation.

You would need something like:

const char *dayname[] = {"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};

...
cout << dayname[(unsigned)d];
...
noz
  • 1,863
  • 13
  • 14
0

Try code below :

int main()
{
    enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
    String days[7] = {"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};
    day d=wednesday;
    cout<<days[d];
    return 0;
}
someone_ smiley
  • 1,006
  • 3
  • 23
  • 42
0

1) If you only want the integer value, you can write an operator << overload:

template<typename _stream>
_stream& operator << (const day& value) {
  _stream << static_cast<int>(value);
  return _stream;
}

Also, consider using enum class instead of a plain enum (if you are allowed to use C++11, of course).

2) I would say there could be 1 such case: namespace constants, say you have a Person class and want to have some in-class constants like MaxAge or MaxNameLength. But even in such cases, wrapping restrictions in something like enum class Settings is usually worth it.

UnknownGosu
  • 854
  • 6
  • 9
0

A type-safe variation on this theme would be to use enum class and use it as a key in std::map

#include <string>
#include <map>
#include <iostream>

int main()
{
    enum class day
    {
        sunday,
        monday,
        tuesday,
        wednesday,
        thursday,
        friday,
        saturday
    };    

    std::map<day,std::string> days = 
    {
        std::make_pair(day::sunday, "Sunday"),
        std::make_pair(day::monday, "Monday"),
        std::make_pair(day::tuesday, "Tuesday"),
        std::make_pair(day::wednesday, "Wednesday"),
        std::make_pair(day::thursday, "Thursday"),
        std::make_pair(day::friday, "Friday"),
        std::make_pair(day::saturday, "Saturday")
    };
    std::cout << days[day::sunday] << std::endl;
}

This means that accessing the map with an integral type will cause a compile-time error.

  • On the other hand, you don't want to write this code by hand, and it's easy enough for your code generator to wrap it in a typesafe function. Which can be made to work even in the constructors of static objects. – James Kanze Jul 24 '13 at 11:15