我如何ToString()在c ++中的枚举?

Cod*_*ero 7 c++

我如何ToString()在c ++中的枚举?在Java和C#中我只会调用ToString.

enum Colours
{
    Red =0,
    Green=1,
    Blue=2
};
Run Code Online (Sandbox Code Playgroud)

我需要创建一个字符串,如:"无效颜色""+颜色+"'已选中.

pmr*_*pmr 20

虽然这通常是通过开关完成的,但我更喜欢数组:

#include <iostream>

namespace foo {
  enum Colors { BLUE = 0, RED, GREEN, SIZE_OF_ENUM };
  static const char* ColorNames[] = { "blue", "red", "green" };

  // statically check that the size of ColorNames fits the number of Colors
  static_assert(sizeof(foo::ColorNames)/sizeof(char*) == foo::SIZE_OF_ENUM
    , "sizes dont match");
} // foo

int main()
{
  std::cout << foo::ColorNames[foo::BLUE] << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果枚举的大小发生更改并且您忘记添加适当的字符串,则显式数组大小具有生成编译时错误的好处.

或者,Boost库中有Boost.Enum.该库尚未正式发布,但非常稳定并提供您想要的.我不会向新手推荐它.

  • 如果您忘记*添加*字符串,它不会生成错误... (3认同)

Lol*_*4t0 15

如何用宏来做一点魔术:

#include <iostream>
#include <string>
#include <vector>


// http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
std::vector<std::string> split(const std::string &text, char sep) {
    std::vector<std::string> tokens;
    int start = 0, end = 0;
    while ((end = text.find(sep, start)) != std::string::npos) {
        tokens.push_back(text.substr(start, end - start));
        start = end + 1;
    }
    tokens.push_back(text.substr(start));
    return tokens;
}

#define ENUM(name, ...)\
enum name \
{\
__VA_ARGS__\
};\
std::vector<std::string> name##Map = split(#__VA_ARGS__, ',');\
    std::string toString(const name v) { return name##Map.at(v);}


ENUM(Color, Red,Green,Blue)


int main(int c, char**v)
{
    std::cout << toString(Red) << toString(Blue);
    return 0;//a.exec();
}
Run Code Online (Sandbox Code Playgroud)

是的,我知道这很难看,你最好不要这样做


SLa*_*aks 8

这本质上是不可能的.

C++枚举只是一组带有编译时名称的数字.
在运行时,它们与普通数字无法区分.

您需要编写一个switch返回字符串的语句.


小智 5

我真的很喜欢@Lol4t0 的宏方法。

我将它扩展为也能够从字符串转换枚举:

#include <iostream>
#include <string>
#include <vector>

// http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
std::vector<std::string> split(const std::string &text, char sep) {
    std::vector<std::string> tokens;
    int start = 0, end = 0;
    while ((end = text.find(sep, start)) != std::string::npos) {
        tokens.push_back(text.substr(start, end - start));
        start = end + 1;
    }
    tokens.push_back(text.substr(start));
    return tokens;
}

#define ENUM(name, ...)\
    enum name\
    {\
        __VA_ARGS__\
    };\
    static const int name##Size = (sizeof((int[]){__VA_ARGS__})/sizeof(int));\
    static const vector<string> name##ToStringMap = split(#__VA_ARGS__, ',');\
    const string name##ToString(const name value)\
    {\
        return name##ToStringMap.at(value);\
    };\
    map<string, name> name##ToFromStringMap(...)\
    {\
        map<string, name> m;\
        name args[name##Size] = { __VA_ARGS__ };\
        \
        int i;\
        for(i = 0; i < name##Size; ++i)\
        {\
            m[name##ToString(args[i])] = args[i];\
        }\
        return m;\
    };\
    static map<string, name> name##FromStringMap = name##ToFromStringMap(__VA_ARGS__);\
    const name name##FromString(const string value, const name defaultValue)\
    {\
        if(name##FromStringMap.count(value) == 0)\
        {\
            return defaultValue;\
        }\
        return name##FromStringMap[value];\
    };
Run Code Online (Sandbox Code Playgroud)

用法:

ENUM(MyEnum, Value1, Value2)

void main()
{
    string valueName = MyEnumToString(MyEnum::Value2);
    MyEnum value = MyEnumFromString(valueName, MyEnum::Value1);
}
Run Code Online (Sandbox Code Playgroud)

我不是 C++ 专家,所以让我知道您的想法或如何做得更好。