#define DEFINE_ENUM_CLASS(Name, ...) \
enum class Name { __VA_ARGS__ }; \
constexpr const char* Name##Strings[] = { #__VA_ARGS__ };
int main()
{
DEFINE_ENUM_CLASS(Color, Red, Green, Blue);
DEFINE_ENUM_CLASS(Bolor, Blue, Cyan, Green);
for (const char* colorName : ColorStrings)
std::cout << colorName << std::endl;
for (const char* bolorName : BolorStrings)
std::cout << bolorName << std::endl;
}
现在打印不在函数中,我正在努力弄清楚如何使打印这些 for 循环之一的行为发生在函数中。
我们需要一个功能性的“map”宏,用于将枚举标记转换为字符串,或者在它们前面添加枚举名称前缀。该宏是this SO post的适配器,占据了程序的大部分长度。
#include <iostream>
// 2-argument functional map with a fixed first argument
#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 EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define MAP_END(...)
#define MAP_OUT
#define MAP_COMMA ,
#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) MAP_NEXT0(test, next, 0)
#define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next)
#define MAP0(f, a, x, peek, ...) f(a,x) MAP_NEXT(peek, MAP1)(f, a, peek, __VA_ARGS__)
#define MAP1(f, a, x, peek, ...) f(a,x) MAP_NEXT(peek, MAP0)(f, a, peek, __VA_ARGS__)
#define MAP_LIST_NEXT1(test, next) MAP_NEXT0(test, MAP_COMMA next, 0)
#define MAP_LIST_NEXT(test, next) MAP_LIST_NEXT1(MAP_GET_END test, next)
#define MAP_LIST0(f, a, x, peek, ...) f(a, x) MAP_LIST_NEXT(peek, MAP_LIST1)(f, a, peek, __VA_ARGS__)
#define MAP_LIST1(f, a, x, peek, ...) f(a, x) MAP_LIST_NEXT(peek, MAP_LIST0)(f, a, peek, __VA_ARGS__)
/**
* Applies the function macro `f` to first argument `a` and each of the remaining parameters.
*/
#define MAP_TWOARG(f, firstarg, ...) EVAL(MAP1(f, firstarg, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
/**
* Applies the function macro `f` to first argument `a` and each of the remaining parameters,
* and inserts commas between the results.
*/
#define MAP_TWOARG_LIST(f, firstarg, ...) EVAL(MAP_LIST1(f, firstarg, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
/**
* Applies the function macro `f` to first argument `a` and each of the remaining parameters.
*/
#define MAP_ONEARG(f, ...) MAP_TWOARG(f, dummy, __VA_ARGS__)
/**
* Applies the function macro `f` to first argument `a` and each of the remaining parameters,
* and inserts commas between the results.
*/
#define MAP_ONEARG_LIST(f, ...) MAP_TWOARG_LIST(f, dummy, __VA_ARGS__)
#define PREFIX_AS_ENUM_CLASS(EnumName, EnumValue) EnumName::EnumValue
#define STR(a,token) #token
template <typename Enum>
constexpr std::underlying_type_t<Enum> to_underlying(Enum x)
{
return static_cast<std::underlying_type_t<Enum>>(x);
}
#define DEFINE_ENUM_CLASS(Name, ...) \
enum class Name { __VA_ARGS__ }; \
constexpr const Name Name##Values[] = { \
MAP_TWOARG_LIST(PREFIX_AS_ENUM_CLASS, Name, __VA_ARGS__) \
}; \
constexpr char const* Name##Strings[] = { MAP_ONEARG_LIST(STR, __VA_ARGS__) }; \
constexpr char const* as_string(Name x, ...) \
{ \
return Name##Strings[to_underlying(x)]; \
}
DEFINE_ENUM_CLASS(Color, Red, Green, Blue);
DEFINE_ENUM_CLASS(Bolor, Blue, Cyan, Green);
int main()
{
std::cout << "Colors:\n";
for (auto color : ColorValues)
std::cout << as_string(color) << std::endl;
std::cout << "-----\nBolors:\n";
for (auto bolor : BolorValues)
std::cout << as_string(bolor) << std::endl;
}
而且它有效(GodBolt.org)。
备注: