该技术来自让某个东西既是 C 标识符又是字符串? https://stackoverflow.com/questions/126277/making-something-both-a-c-identifier-and-a-string可以在这里使用。
与通常的预处理器内容一样,编写和理解预处理器部分可能很困难,包括将宏传递给其他宏并涉及使用 # 和 ## 运算符,但使用它非常简单。我发现这种风格对于长枚举非常有用,因为两次维护相同的列表确实很麻烦。
工厂代码 - 仅输入一次,通常隐藏在标题中:
枚举工厂.h:
// expansion macro for enum value definition
#define ENUM_VALUE(name,assign) name assign,
// expansion macro for enum to string conversion
#define ENUM_CASE(name,assign) case name: return #name;
// expansion macro for string to enum conversion
#define ENUM_STRCMP(name,assign) if (!strcmp(str,#name)) return name;
/// declare the access function and define enum values
#define DECLARE_ENUM(EnumType,ENUM_DEF) \
enum EnumType { \
ENUM_DEF(ENUM_VALUE) \
}; \
const char *GetString(EnumType dummy); \
EnumType Get##EnumType##Value(const char *string); \
/// define the access function names
#define DEFINE_ENUM(EnumType,ENUM_DEF) \
const char *GetString(EnumType value) \
{ \
switch(value) \
{ \
ENUM_DEF(ENUM_CASE) \
default: return ""; /* handle input error */ \
} \
} \
EnumType Get##EnumType##Value(const char *str) \
{ \
ENUM_DEF(ENUM_STRCMP) \
return (EnumType)0; /* handle input error */ \
} \
工厂使用
一些Enum.h:
#include "enumFactory.h"
#define SOME_ENUM(XX) \
XX(FirstValue,) \
XX(SecondValue,) \
XX(SomeOtherValue,=50) \
XX(OneMoreValue,=100) \
DECLARE_ENUM(SomeEnum,SOME_ENUM)
一些Enum.cpp:
#include "someEnum.h"
DEFINE_ENUM(SomeEnum,SOME_ENUM)
该技术可以轻松扩展,以便 XX 宏接受更多参数,并且您还可以准备更多宏来替代 XX 以满足不同的需求,类似于我在本示例中提供的三个宏。
与使用 #include / #define / #undef 的 X 宏的比较
虽然这类似于其他人提到的 X-Macros,但我认为这个解决方案更优雅,因为它不需要 #undefing 任何东西,这允许您隐藏更多复杂的东西在工厂头文件中 - 头文件当您需要定义一个新的枚举时,您根本不会触及它,因此新的枚举定义要短得多、更干净。