How to make ToString () enum in C ++?

How to make ToString () enum in C ++? In Java and C #, I would just call ToString.

enum Colours { Red =0, Green=1, Blue=2 }; 

I need to create a string like "Invalid color" "+ color +" ".

+6
source share
8 answers

Although this is usually done using switches, I prefer arrays:

 #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; } 

The explicit size of the array has the advantage of generating compilation time; the error should change the size of the enumeration and you will forget to add the corresponding line.

In addition, the Boost repository has Boost.Enum. The library is not officially released, but it is stable enough and provides what you want. I would not recommend it to a beginner.

+18
source

How about magic with macros:

 #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(); } 

Yes, I understand that this is ugly, and you better not do it.

+15
source

This is inherently impossible.

A C ++ enumeration is just a collection of numbers with compile-time names.
At run time, they are indistinguishable from ordinary numbers.

You need to write a switch that returns a string.

+8
source
 enum Color { Red =0, Green=1, Blue=2 }; std::string ColorMap[] = { "Red", "Green","Blue" }; 

Use ColorMap[c] to get a string representation:

 std::string msg = "Invalid colour '" + ColorMap[c] + "' selected."; 

However, if the enum values ​​are not continuous, you can use std::map instead:

 enum Color { Red = 0x1, Green = 0x2, Blue = 0x4, Black = 0x8, }; //C++11 only, as it uses std::initializer_list std::map<Color, std::string> ColorMap = { {Red, "Red"}, {Green, "Green"}, {Blue, "Blue"}, {Black, "Black"} }; //same as before! std::string msg = "Invalid colour '" + ColorMap[c] + "' selected."; 
+3
source

I really like the @ Lol4t0 macro approach.

I expanded it to be able to convert an enum from a string too:

 #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];\ }; 

Using:

 ENUM(MyEnum, Value1, Value2) void main() { string valueName = MyEnumToString(MyEnum::Value2); MyEnum value = MyEnumFromString(valueName, MyEnum::Value1); } 

I am not an expert in C ++, so let me know what you think and how best.

+3
source

You need to do it manually, i.e.

 const char* ToString(Colours co) { switch(co) { case Red: return "Red"; // ... } } 

A lookup table will also be available. I also saw people using their own scripts to create such material on top of the source code.

+1
source

You can store names in an array of strings indexed by enum values.

 enum Colours { Red =0, Green=1, Blue=2 }; char* names[3] = {"Red", "Green", "Blue"}; 

Then you can type: "Invalid colour '" + names[colour] + "' selected."

But this approach may not be very useful if you do not define enum values ​​sequentially. In this case, this approach will destroy memory. As Alexander Gessler noted, using a function with a switch over an enum value would be useful. Another alternative could be a map from STL.

0
source

As @FlopCoder said:

 enum Colours { Red =0, Green=1, Blue=2 }; char* ColourNames[] = { "Red", "Green", "Blue" }; int colour = Green; printf( "Invalid colour '%s' selected.", ColourNames[ colour ] ); 

This, of course, will only work if your enumeration starts at 0 and is continuous.
The @Nawaz style is more stylish C ++ though.

0
source

Source: https://habr.com/ru/post/907704/


All Articles