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...
Back in 2011 I spent a weekend fine-tuning a macro-based solution and ended up never using it.
My current procedure is to start Vim, copy the enumerators in an empty switch body, start a new macro, transform the first enumerator into a case statement, move the cursor to the beginning of the next line, stop the macro and generate the remaining case statements by running the macro on the other enumerators.
Vim macros are more fun than C++ macros.
Real-life example:
I will create this:
And that's how I get by.
Native support for enum stringification would be much better though. I'm very interested to see the results of the reflection workgroup in C++17.
An alternative way to do it was posted by @sehe in the comments.
my solution is without macro usage.
advantages:
disadvantages:
so... until the day that C++ implements the C# Enum.Parse functionality, I will be stuck with this:
The following solution is based on a
std::array<std::string,N>
for a given enum.For
enum
tostd::string
conversion we can just cast the enum tosize_t
and lookup the string from the array. The operation is O(1) and requires no heap allocation.For
std::string
toenum
conversion we would have to make a linear search over the array and cast the array index toenum
.Try it here with usage examples: http://coliru.stacked-crooked.com/a/e4212f93bee65076
Edit: Reworked my solution so the custom Enum can be used inside a class.
I wrote a library for solving this problem, everything happens in compiling time, except for getting the message.
Usage:
Use macro
DEF_MSG
to define a macro and message pair:CODE_OK
is the macro to use, and"OK!"
is the corresponding message.Use
get_message()
or justgm()
to get the message:Use
MSG_NUM
to find out how many macros have been defined. This will automatically increse, you don't need to do anything.Predefined messages:
Project: libcodemsg
The library doesn't create extra data. Everything happens in compiling time. In
message_def.h
, it generates anenum
calledMSG_CODE
; inmessage_def.c
, it generates a variable holds all the strings instatic const char* _g_messages[]
.In such case, the library is limited to create one
enum
only. This is ideal for return values, for example:Another thing I like this design is you can manage message definitions in different files.
I found the solution to this question looks much better.
This gist provides a simple mapping based on C++ variadic templates.
This is a C++17-simplified version of the type-based map from the gist:
An example usage:
The
map<KeyValues...>
can be used in both directions:fasion_names::get(fasion::emo)
fasion_names::get("emo")
This example is available on godbolt.org
Result from
gcc-7 -std=c++1z -Ofast -S
Well, yet another option. A typical use case is where you need constants for the HTTP verbs as well as using its string version values.
The example:
The VERB class: