Skip to content

Instantly share code, notes, and snippets.

@riogu
Last active July 18, 2025 22:16
Show Gist options
  • Select an option

  • Save riogu/1d3ad87b662916c39e7a6ae44e56d054 to your computer and use it in GitHub Desktop.

Select an option

Save riogu/1d3ad87b662916c39e7a6ae44e56d054 to your computer and use it in GitHub Desktop.
printable C++ enums with macros

a few lines of macros for making a printable enum.

#include "printable-enum.hpp"
make_enum(my_enum, foo, bar, what, something);
make_enum(another_enum, foo, bar, gaming, something);
#include <print>
int main() {
my_enum somevar = my_enum::bar;
std::print("my enum was: {}\n", somevar.to_str());
another_enum var = another_enum::gaming;
std::print("my enum was: {}\n", var.to_str());
switch (somevar) {
case my_enum::foo:
case my_enum::what:
default:
break;
}
}
#pragma once
#define EVAL0(...) __VA_ARGS__
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL5(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#ifdef _MSC_VER
// MSVC needs more evaluations
#define EVAL6(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
#define EVAL(...) EVAL6(EVAL6(__VA_ARGS__))
#else
#define EVAL(...) EVAL5(__VA_ARGS__)
#endif
#define EMPTY()
#define DEFER(id) id EMPTY()
#define MAP_END(...)
#define MAP_OUT
#define MAP_GET_END2() 0, MAP_END
#define MAP_GET_END1(...) MAP_GET_END2
#define MAP_GET_END(...) MAP_GET_END1
#define MAP_NEXT0(test, next, ...) next MAP_OUT
#define MAP_NEXT1(test, next) DEFER ( MAP_NEXT0 ) ( test, next, 0)
#define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next)
#define MAP_INC(X) MAP_INC_ ## X
#define MAP0(f, x, peek, ...) f(x) DEFER ( MAP_NEXT(peek, MAP1) ) ( f, peek, __VA_ARGS__ )
#define MAP1(f, x, peek, ...) f(x) DEFER ( MAP_NEXT(peek, MAP0) ) ( f, peek, __VA_ARGS__ )
#define map_macro(f, ...) EVAL(MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
#include <string>
#define enum_str_repr(_v) case _v: return #_v;
#define make_enum(name, ...) \
struct name { \
enum impl { __VA_ARGS__ } value; \
\
[[nodiscard]] constexpr std::string to_str() { \
switch(value) { \
map_macro(enum_str_repr, __VA_ARGS__) \
default: return "unknown enum."; \
} \
} \
\
constexpr operator impl(){ return value; } \
name(impl some): value(some){} \
name() {} \
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment