0

Using C++ (Visual Studio). I'm trying to find a solution for converting an enum to a string. I came across X Macros (http://drdobbs.com/cpp/184401387) which seems to be a reasonable solution but I'm having a hard time getting it to work inside of a class. All the examples I've seen show everything defined outside of a class.

// ColorNames.h
X(Red, "Red"),
X(Blue, "Blue"),
...


// MyClass.h
class MyClass
{
public:
    MyClass();
    virtual ~MyClass();

    #define X(a, b) a
    enum Colors {
        #include "ColorNames.h"
    };
    #undef X

    #define X(a, b) b
    char *colorNameStrings_[] = {
        #include "ColorNames.h"
    };
    #undef X
}

The IDE chokes on the line *colorNameStrings_[] =... I guess because you can't initialize a data member variable in the header file? How do I get this to work?

User
  • 62,498
  • 72
  • 186
  • 247
  • 1
    My goal is to have an enum to string mapping. The idea of X Macros, I believe, is to help guarantee that mapping stays in sync. – User Sep 08 '11 at 20:57

3 Answers3

3

The problem is that you can't initialize a non static constant inside a class definition.

You would probably have to do it like that:

// MyClass.h
class MyClass
{
public:
    MyClass();
    virtual ~MyClass();

    #define X(a, b) a
    enum Colors {
        #include "ColorNames.h"
    };
    #undef X

    static const char * colorNameStrings_[];
};

And in the .cpp file:

// MyClass.cpp
#include "MyClass.h"

#define X(a, b) b
const char * MyClass::colorNameStrings_[] = {
    #include "ColorNames.h"
};
#undef X
Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111
2

Instead of using X-Macros, consider using the Boost.Preprocessor library. The initial, one-time definition of the code generation macros takes a bit of work, but the end result is far cleaner and much easier to reuse.

I provided a basic implementation of a generic, Boost.Preprocessor-based enum-to-string-name conversion in an answer to "How to convert an enum type variable to a string?"

Community
  • 1
  • 1
James McNellis
  • 348,265
  • 75
  • 913
  • 977
1

Use a struct like this

struct convert
{
     std::map<MyEnum, std::string> mapping;

     convert() 
     { 
          mapping[SOME_ENUM_VALUE] = "SomeValue"; 
          // etc to fill map
     }

     std::string operator()(MyEnum enum)
     {
         return mapping[enum];    
     }

};

Then use like this:

convert c;
std::string ret = c(myenum);  //calls operator()
Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
  • That is ridiculously verbose. Also, why use a struct when a function would do? – Etienne de Martel Sep 08 '11 at 20:57
  • @Etienne, that's just how I used to do it, when I had loads of enums in need of conversion. – Tony The Lion Sep 08 '11 at 21:00
  • 1
    A benefit of doing it with a struct is that you can define them in more varied scope. With a function you are restricted from inline in a function and fully in a header. – Tom Kerr Sep 08 '11 at 21:07
  • The basic problem with this that X Macros tries to solve is that the programmer must remember to keep the enum and the std::map in sync. – User Sep 08 '11 at 22:21