Is there a simple way to convert C++ enum to string?

后端 未结 30 2801
我在风中等你
我在风中等你 2020-11-22 10:37

Suppose we have some named enums:

enum MyEnum {
      FOO,
      BAR = 0x50
};

What I googled for is a script (any language) that scans all

30条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-11-22 10:59

    This is a modification to @user3360260 answer. It has the following new features

    • MyEnum fromString(const string&) support
    • compiles with VisualStudio 2012
    • the enum is an actual POD type (not just const declarations), so you can assign it to a variable.
    • added C++ "range" feature (in form of vector) to allow "foreach" iteration over enum

    Usage:

    SMART_ENUM(MyEnum, ONE=1, TWO, THREE, TEN=10, ELEVEN)
    MyEnum foo = MyEnum::TWO;
    cout << MyEnum::toString(foo);  // static method
    cout << foo.toString();         // member method
    cout << MyEnum::toString(MyEnum::TWO);
    cout << MyEnum::toString(10);
    MyEnum foo = myEnum::fromString("TWO");
    
    // C++11 iteration over all values
    for( auto x : MyEnum::allValues() )
    {
      cout << x.toString() << endl;
    }
    

    Here's the code

    #define SMART_ENUM(EnumName, ...)                                   \
    class EnumName                                                      \
    {                                                                   \
    public:                                                             \
        EnumName() : value(0) {}                                        \
        EnumName(int x) : value(x) {}                                   \
    public:                                                             \
        enum {__VA_ARGS__};                                             \
    private:                                                            \
        static void initMap(std::map& tmp)                     \
        {                                                               \
            using namespace std;                                        \
                                                                        \
            int val = 0;                                                \
            string buf_1, buf_2, str = #__VA_ARGS__;                    \
            replace(str.begin(), str.end(), '=', ' ');                  \
            stringstream stream(str);                                   \
            vector strings;                                     \
            while (getline(stream, buf_1, ','))                         \
                strings.push_back(buf_1);                               \
            for(vector::iterator it = strings.begin();          \
                                                    it != strings.end(); \
                                                    ++it)                \
            {                                                           \
                buf_1.clear(); buf_2.clear();                           \
                stringstream localStream(*it);                          \
                localStream>> buf_1 >> buf_2;                           \
                if(buf_2.size() > 0)                                    \
                    val = atoi(buf_2.c_str());                          \
                tmp[val++] = buf_1;                                     \
            }                                                           \
        }                                                               \
        int value;                                                      \
    public:                                                             \
        operator int () const { return value; }                         \
        std::string toString(void) const {                              \
                return toString(value);                                 \
        }                                                               \
        static std::string toString(int aInt)                           \
        {                                                               \
            return nameMap()[aInt];                                     \
        }                                                               \
        static EnumName fromString(const std::string& s)                \
        {                                                               \
            auto it = find_if(nameMap().begin(), nameMap().end(), [s](const std::pair& p) { \
                return p.second == s;                                   \
            });                                                         \
            if (it == nameMap().end()) {                                \
            /*value not found*/                                         \
                throw EnumName::Exception();                            \
            } else {                                                    \
                return EnumName(it->first);                             \
            }                                                           \
        }                                                               \
        class Exception : public std::exception {};                     \
        static std::map& nameMap() {                   \
          static std::map nameMap0;                    \
          if (nameMap0.size() ==0) initMap(nameMap0);                   \
          return nameMap0;                                              \
        }                                                               \
        static std::vector allValues() {                      \
          std::vector x{ __VA_ARGS__ };                       \
          return x;                                                     \
        }                                                               \
        bool operator<(const EnumName a) const { return (int)*this < (int)a; } \
    };         
    

    Note that the conversion toString is a fast has lookup, while the conversion fromString is a slow linear search. But strings are so expensive anyways(and the associated file IO), I didn't feel the need to optimize or use a bimap.

提交回复
热议问题