#define PARENS () // Rescan macro tokens 256 times #define EXPAND(...) EXPAND4(EXPAND4(EXPAND4(EXPAND4(__VA_ARGS__)))) #define EXPAND4(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__)))) #define EXPAND3(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__)))) #define EXPAND2(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__)))) #define EXPAND1(...) __VA_ARGS__ #define FOR_EACH(macro, name, ...) \ __VA_OPT__(EXPAND(FOR_EACH_HELPER(macro, name, __VA_ARGS__))) #define FOR_EACH_HELPER(macro, name, a1, ...) \ macro(name, a1) \ __VA_OPT__(FOR_EACH_AGAIN PARENS(macro, name, __VA_ARGS__)) #define FOR_EACH_AGAIN() FOR_EACH_HELPER #define ENUM_VARIANT0(name, val) name = val, #define ENUM_VARIANT(name, tuple) ENUM_VARIANT0 tuple #define TUPLE(x, y) x, y #define LPAREN ( #define TO_STRING_CASE0(type, name, val) \ case type::name: \ return #name; #define TO_STRING_CASE(type, tuple) TO_STRING_CASE0 LPAREN type, TUPLE tuple) #define FROM_INT_CASE0(type, name, val) \ case val: \ return type::name; #define FROM_INT_CASE(type, tuple) FROM_INT_CASE0 LPAREN type, TUPLE tuple) #define ENUM(name, type, ...) \ enum class name : type { \ FOR_EACH(ENUM_VARIANT, name, __VA_ARGS__) \ }; \ inline const char* \ name##_to_string(name _e) \ { \ switch (_e) { \ FOR_EACH(TO_STRING_CASE, name, __VA_ARGS__) \ default: \ return "UNKNOWN"; \ } \ } \ inline name \ to_##name(type _t, name _unknown) \ { \ switch (_t) { \ FOR_EACH(FROM_INT_CASE, name, __VA_ARGS__) \ default: \ return _unknown; \ } \ } #define SUM_TYPE_UNION_MEMBER0(type, var) type var; #define SUM_TYPE_UNION_MEMBER(name, tuple) SUM_TYPE_UNION_MEMBER0 tuple #define SUM_TYPE_ENUM_MEMBER0(type, var) var, #define SUM_TYPE_ENUM_MEMBER(name, tuple) SUM_TYPE_ENUM_MEMBER0 tuple #define SUM_TYPE_CONSTRUCTOR0(name, type, val) \ name(type&& arg) \ : tag(Tag::val) \ { \ value.val = std::move(arg); \ } #define SUM_TYPE_CONSTRUCTOR(name, tuple) SUM_TYPE_CONSTRUCTOR0 LPAREN name, TUPLE tuple) #define SUM_TYPE(name, ...) \ class name { \ public: \ union { \ FOR_EACH(SUM_TYPE_UNION_MEMBER, name, __VA_ARGS__) \ } value; \ enum class Tag { \ void_, \ FOR_EACH(SUM_TYPE_ENUM_MEMBER, name, __VA_ARGS__) \ } tag; \ \ name() \ : tag(Tag::void_) \ { \ } \ FOR_EACH(SUM_TYPE_CONSTRUCTOR, name, __VA_ARGS__) \ };