Thursday 2 November 2017

c++ - enum to string in modern C++11 / C++14 / C++17 and future C++20

itemprop="text">

Contrary to all other similar
questions, this question is about using the new C++
features.





After reading
many answers, I did not yet find
any:






Example



An
example is often better than a long explanation.
You can compile and run this
snippet on rel="noreferrer">Coliru.
( href="http://coliru.stacked-crooked.com/a/bb58819257b6df50" rel="noreferrer">Another
former example is also
available)



#include

#include


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 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 valueless duplication of href="https://stackoverflow.com/a/10177840/938111">other answers or href="https://stackoverflow.com/a/18791363/938111">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 :
    having any allowed
    (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...)

  • href="https://en.cppreference.com/w/cpp/language/constexpr"
    rel="noreferrer">constexpr (C++11, then relaxed in
    C++14/17/20)

  • href="https://en.cppreference.com/w/cpp/language/noexcept"
    rel="noreferrer">noexcept
    (C++11)


  • href="https://en.wikipedia.org/wiki/C%2B%2B17" rel="noreferrer">C++17/ href="https://en.wikipedia.org/wiki/C%2B%2B20" rel="noreferrer">C++20
    friendly snippet



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...


itemprop="text">
class="normal">Answer






#include


enum Color { RED = 2, BLUE = 4, GREEN = 8
};


Color color = Color::RED;
auto color_name =
magic_enum::enum_name(color);
// color_name ->
"RED"

std::string color_name{"GREEN"};
auto color =
magic_enum::enum_cast(color_name)
if (color.has_value())
{
// color.value() ->
Color::GREEN
};



For
more examples check home repository rel="noreferrer">https://github.com/Neargye/magic_enum.



Where
is the drawback?



This library uses a
compiler-specific hack (based on __PRETTY_FUNCTION__ /
__FUNCSIG__), which works on Clang >= 5, MSVC >= 15.3 and
GCC >= 9.



Enum value must be in range
[MAGIC_ENUM_RANGE_MIN, MAGIC_ENUM_RANGE_MAX]. By default
MAGIC_ENUM_RANGE_MIN = -128, MAGIC_ENUM_RANGE_MAX =
128
.





  • If
    need another range for all enum types by default, redefine the macro
    MAGIC_ENUM_RANGE_MIN and
    MAGIC_ENUM_RANGE_MAX.


  • If
    need another range for specific enum type, add specialization enum_range for necessary
    enum type.



    #include


    enum number { one = 100, two = 200, three =
    300 };

    namespace magic_enum {
    template
    <>

    struct enum_range {
    static
    constexpr int min = 100;
    static constexpr int max =
    300;
    };
    }



No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...