3

My current program uses 3 different enums:

enum ThingEnum{
    Thing1 = 0,
    Thing2 = 1,
    Thing3 = 2,
    OtherThing = 3
};
enum ReturnEnum {
    Success = 4,// the method did what it is supposed to
    Error1 = 5,// an error occured
    Error2 = 6,// an error occured
    Error3 = 7,// an error occured
    Error4 = 8,// a fatal error occured program must terminate
    Pointer = 9// the method may need to be called again
};
enum TypeEnum {
    Type1 = 10,
    Type2 = 11,
    Type3 = 12,
    Type4 = 13,
    OtherType = 14
};  

What I want to do is create a global function that takes an enum and returns a string (as the value of an enum is really just a specialized variable name that always has a value). Is it possible to create a function that takes a generic enum? e.g.

string enumToString (enum _enum){}

or would I have to make a function for each different enum? Just a possible thought I did some reading, and some compilers allow for a Enum to resolve to an int so could I pass the enum as an int and then work with it?

gardian06
  • 1,496
  • 3
  • 20
  • 34
  • So what you want to do is convert an enum value to a string? Maybe you should revise the question title... – tenfour Feb 02 '12 at 11:41
  • `as the value of an enum is really just a specialized variable name that always has a value` whut – Lightness Races in Orbit Feb 02 '12 at 11:52
  • @Lightness when the compiler reads enum Ex{this, thisTo}; it will generate values for them (unless they are set to specifics), but to access them you need to use the name representing that value as kind of like using a resolution operator to get to an exact method in a class. as literature on enums will state "an Enum will resolve to a specific value (an int address), but even if that value is known the reverse conversion will never resolve" – gardian06 Feb 02 '12 at 12:18
  • 1
    @gardian06: Yes, I know what enums are, thanks. I was wondering what on earth the quoted passage was supposed to mean. – Lightness Races in Orbit Feb 02 '12 at 14:01
  • @LightnessRacesinOrbit it means that you can use an enum the same that in C you could use #define CONST_THING = 0x0A and every time you use CONST_THING it will always resolve to that value. the same way that enum Ex{this, thisTo} every time you use thisTo it will always resolve to the value assigned to it (assuming scope) hens Ex is a specialized variable, and thisTo is its value. yes the better statement probably should have been "as an enum is really just a specialized variable that has preset known values" – gardian06 Feb 03 '12 at 00:56
  • So basically all you're saying is that a object of enum type is a object. There really isn't anything particularly special about it. – Lightness Races in Orbit Feb 03 '12 at 01:37

4 Answers4

2

There are two options of "ToString-like" function implementation:

  1. Implement a simple static switch-case function.

Code:

std::string ThingEnumToString(ThingEnum thing)
{
    switch (thing) {
    case Thing1:
        return std::string("Thing1");
    case Thing2:    
        return std::string("Thing2");
    case Thing3:
        return std::string("Thing3");        
    case OtherThing:
        return std::string("OtherThing");
    default:
        throw std::invalid_argument("thing");
        break;
    }
}
  1. Implement a static function with a dictionary lookup.

Code:

typedef std::map<ThingEnum, std::string> ThingsMap;

static ThingsMap GetThingsMap()
{
    ThingsMap things_map;
    things_map.insert(ThingsMap::value_type(Thing1, std::string("Thing1")));
    things_map.insert(ThingsMap::value_type(Thing2, std::string("Thing2")));
    things_map.insert(ThingsMap::value_type(Thing3, std::string("Thing3")));
    things_map.insert(ThingsMap::value_type(OtherThing, std::string("OtherThing")));
    return things_map;
}

static std::string ThingEnumToString(ThingEnum thing)
{
    static const ThingsMap things(GetThingsMap());
    ThingsMap::const_iterator it = things.find(thing);
    if (it != things.end()) {
        return it->second;
    } else {
        throw std::invalid_argument("thing");
    }
}
2

This is one of those cases where I'd advocate the use of macros to make your code more intelligible / maintainable (and remove at least one source of errors)

Thus

  #define TOSTRING(name) case name: return #name
  switch (val)
  {
      TOSTRING(Thing1);
      TOSTRING(Thing2);
      default:
         //bad things happened.
   }
Tom Tanner
  • 9,244
  • 3
  • 33
  • 61
1

No, enums have no implicit base class.

You can use templates, or function overloading. But, yes, you're going to have to do it by hand.

There are some tricks for enum→string "conversion" listed here.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

enum names only make sense before compilation. I don't think there's a portable or standard-defined way of doing this in a clean fashion.

You could do it as follows:

std::string getName(ThingEnum x)
{
   switch (x)
   {
   case Thing1:
      return "Thing1";
   case Thing2:
      return "Thing2";
   //....
   }
}
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • basically if I can get the enum into the function then I can basically do like a case switch to return the right string. I don't necessarily want to have it return its own name, but at least have a logic check done on it. – gardian06 Feb 02 '12 at 11:50
  • @gardian06 yes, like in my edit, but it's not generic(which wouldn't make sense anyway) and you have to hardcode a lot of stuff. Why would you need this anyway? – Luchian Grigore Feb 02 '12 at 11:54
  • to generate log messages. because I will have to be integrating stuff on top of these, and "method returned: 6" is not as meaningful as "method returned: Error2" for debugging. – gardian06 Feb 02 '12 at 12:05