Contrary to all other similar questions, this question is about using the new C++ features.
- 2008 c Is there a simple way to convert C++ enum to string?
- 2008 c Easy way to use variables of enum types as string in C?
- 2008 c++ How to easily map c++ enums to strings
- 2008 c++ Making something both a C identifier and a string?
- 2008 c++ Is there a simple script to convert C++ enum to string?
- 2009 c++ How to use enums as flags in C++?
- 2011 c++ How to convert an enum type variable to a string?
- 2011 c++ Enum to String C++
- 2011 c++ How to convert an enum type variable to a string?
- 2012 c How to convert enum names to string in c
- 2013 c Stringifying an conditionally compiled enum in C
After reading many answers, I did not yet find any:
- Elegant way using C++11, C++14 or C++17 new features
- Or something ready-to-use in Boost
- Else something planned for C++20
Example
An example is often better than a long explanation.
You can compile and run this snippet on Coliru.
(Another former example is also available)
#include <map>
#include <iostream>
struct MyClass
{
enum class MyEnum : char {
AAA = -8,
BBB = '8',
CCC = AAA + BBB
};
};
// Replace magic() by some faster compile-time generated code
// (you're allowed to replace the return type with std::string
// if that's easier for you)
const char* magic (MyClass::MyEnum e)
{
const std::map<MyClass::MyEnum,const char*> MyEnumStrings {
{ MyClass::MyEnum::AAA, "MyClass::MyEnum::AAA" },
{ MyClass::MyEnum::BBB, "MyClass::MyEnum::BBB" },
{ MyClass::MyEnum::CCC, "MyClass::MyEnum::CCC" }
};
auto it = MyEnumStrings.find(e);
return it == MyEnumStrings.end() ? "Out of range" : it->second;
}
int main()
{
std::cout << magic(MyClass::MyEnum::AAA) <<'\n';
std::cout << magic(MyClass::MyEnum::BBB) <<'\n';
std::cout << magic(MyClass::MyEnum::CCC) <<'\n';
}
Constraints
- Please no invaluable duplication of other answers or basic link.
- Please avoid bloat macro-based answer, or try to reduce the
#define
overhead as minimum as possible. - Please no manual
enum
->string
mapping.
Nice to have
- Support
enum
values starting from a number different from zero - Support negative
enum
values - Support fragmented
enum
values - Support
class enum
(C++11) - Support
class enum : <type>
having any allowed<type>
(C++11) - Compile-time (not run-time) conversions to a string,
or at least fast execution at run-time (e.g.std::map
is not a great idea...) constexpr
(C++11, relaxed in C++14)noexcept
(C++11)- snippet C++14/C++17 friendly
- C++ State of the art
One possible idea could be using the C++ compiler capabilities to generate C++ code at compilation-time using meta-programming tricks based on variadic template class
and constexpr
functions...
You could use a reflection library, like Ponder:
Just generate your enums. Writing a generator for that purpose is about five minutes' work.
Generator code in java and python, super easy to port to any language you like, including C++.
Also super easy to extend by whatever functionality you want.
example input:
generated header:
generated cpp file
And the generator, in a very terse form as a template for porting and extension. This example code really tries to avoid overwriting any files but still use it at your own risk.
And a port to Python 3.5 because different enough to be potentially helpful
My answer is here.
You can get enum value names and these indices simultaneously as deque of string.
This method only needs little copy and paste and edit.
Obtained result needs type-casting from size_t to enum class type when you need enum class type value, but I think it is a very portable and powerful way to treat enum class.
This is similar to Yuri Finkelstein; but does not required boost. I am using a map so you can assign any value to the enums, any order.
Declaration of enum class as:
The following code will automatically create the enum class and overload:
No boost required, all required functions provided.
Code:
Example:
You can run the code here
If your
enum
looks likeYou can move the content of the
enum
to a new file:And then the values can be surrounded by a macro:
Next step may be include the items in the
enum
again:And finally you can generate utility functions about this
enum
:The solution can be applied to older C++ standards and it does not use modern C++ elements but it can be used to generate lot of code without too much effort and maintenance.
I don't know if you're going to like this or not, I'm not pretty happy with this solution but it is a C++14 friendly approach because it is using template variables and abusing template specialization:
The worst about this approach is that is a pain to maintain, but it is also a pain to maintain some of other similar aproaches, aren't they?
Good points about this aproach:
Live example
Edit
Misterious user673679 you're right; the C++14 variable template approach doesn't handles the runtime case, it was my fault to forget it :(
But we can still use some modern C++ features and variable template plus variadic template trickery to achieve a runtime translation from enum value to string... it is as bothersome as the others but still worth to mention.
Let's start using a template alias to shorten the access to a enum-to-string map:
Then, the variadic template trickery:
The "best trick" here is the use of variable template for the map which contains the values and names of each enum entry; this map will be the same in each translation unit and have the same name everywhere so is pretty straightforward and neat, if we call the
initialize
function like this:We are asigning names to each
MyEnum
entry and can be used in runtime:But can be improved with SFINAE and overloading
<<
operator:With the correct
operator <<
now we can use the enum this way:This is also bothersome to maintain and can be improved, but hope you get the idea.
Live example