TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.37K subscribers
Post #941 5.04K
​​magic_enum
#опытным

Много раз уже упоминали эту библиотечку в комментах, пора удостоить ее отдельного поста.

В чем проблема: хочется enum сериализовывать/десериализовывать в строку и из строки. То есть значение перечислителя заменить его строковым представлением в коде.

Такая задача требует рефлексии, которая в С++ только в 26 стандарте появится. Рефлексия - способность программы знать о том, как она написана на языке программирования. В скомпилированной программе перечислитель это всего лишь число, а чтобы получить имя, которое он имел в С++ коде, в программе должна эта информация где-то сохраниться.

Ну то есть, если у вас нет С++26, то нужно терпеть(но мы привыкли) и писать костыли. Что делается обычно:

enum class Color { RED, GREEN, BLUE };

std::unordered_map<Color, std::string> map = {{Color::RED, "RED"}, {Color::GREEN, "GREEN"}, {Color::BLUE, "BLUE"}};

std::cout << map[Color::RED] << std::endl;


Для больших перечислений опупеете писать эти мапы, плюс код в принципе засоряется ими.

Но на любую проблему стандартных плюсов найдется своя библиотека, которая ее решит.
В этом случае пригодится magic_enum.

Это хэдэр-онли С++17 библиотечка, которая предоставляет статическую рефлексию для перечислений и работает без макросни в интерфейсе и без бойлерплейта.


Простой пример:

Color color = Color::RED;
std::string color_name = magic_enum::enum_name(color);
assert(color_name == "RED);


Как это работает?

magic_enum рассчитан на работу с небольшими enum'ами. По дефолту интервал underlying значений от -128 до 127.

Если сильно упрощенно, то magic_enum пытается инстанцировать специальную функцию для каждого значения из этого интервала. Так как шаблонный параметр будет NTTP, его значение будет вшито в саму сигнатуру функции. А ее можно получить с помощью __PRETTY_FUNCTION__ или __FUNCSIG__:

template <auto V>
constexpr std::string_view get_enum_name() {
return extract_name(PRETTY_FUNCTION);
}


Только для реально существующих перечислителей __PRETTY_FUNCTION__ будет содержать корректное имя. Так и происходит маппинг значений перечислителей на их имена.

Вот примеры сигнатуры функции для существующего и несуществующего перечислителя:

enum class Color { RED, GREEN, BLUE };

constexpr Color c = static_cast<Color>(4);
get_enum_name<c>(); // constexpr void get_enum_name() [with auto V = (Color)4]
get_enum_name<Color::GREEN>(); // constexpr void get_enum_name() [with auto V = Color::GREEN]


Чтобы это все реализовать и вместе собрать нужно еще много шаблонной магии, но суть такова.

magic_enum еще много чего умеет:

👉🏿 Обратный маппинг имен на значения перечисления

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


👉🏿 Доступ к элементам перечисления по индексу
std::size_t i = 0;
Color color = magic_enum::enum_value<Color>(i);


👉🏿 Можно получить количество элементов enum'а:
constexpr std::size_t color_count = magic_enum::enum_count<Color>();


👉🏿 Свои перегруженные io операторы:
using magic_enum::iostream_operators::operator<<; // out-of-the-box ostream operators for enums.
Color color = Color::BLUE;
std::cout << color << std::endl; // "BLUE"


и много чего еще.

Обзор фукнциональности можно найти в репе на гитхабе. Обратите особое внимание на ограничения библиотеки.

Use magic. Stay cool.

#tools #template
  • 🔥 29
  • 👍 13
  • ❤ 11
  • 😱 2
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →