我正在尝试构建一个 X 宏,它允许生成一个带有一堆有用函数(例如
.toString()
)的枚举。我得到的版本可以这样实现:
#define MAKE_ENUM \
ENUM_NAME( LanguageId ) \
ENUM_TYPE( unsigned int ) \
ENUM_ENTRY( English, 0 )\
ENUM_ENTRY( French ) \
ENUM_ENTRY( German ) \
ENUM_ENTRY( Italian ) \
ENUM_ENTRY( Spanish ) \
ENUM_ENTRY( Polish ) \
ENUM_ENTRY( Korean, 128 ) \
ENUM_ENTRY( ChineseTraditional, 129 ) \
ENUM_ENTRY( ChineseSimplified, 130 ) \
ENUM_ENTRY( Japanese, 131 )
#include "GenericToolbox.MakeEnum.h"
#undef MAKE_ENUM
X 宏
MAKE_ENUM
的部署是在标题GenericToolbox.MakeEnum.h
下完成的。
这个版本的效果符合预期。但是我希望
ENUM_TYPE
成为可选参数,因此有时用户不会设置它,并且枚举将被定义为默认 int
。
为此,我需要弄清楚 MAKE_ENUM 的展开是否为空。我想出的版本是这样的:
#define TEMP_EXPAND(x) x
#define TEMP_SELECT_THIRD(_1,_2,num,...) num
#define TEMP_IS_NOT_EMPTY_IMPL(...) TEMP_EXPAND(TEMP_SELECT_THIRD(__VA_ARGS__,1,0))
#define TEMP_ARGS_DUMMY( ... ) dummy,##__VA_ARGS__
#define TEMP_IS_NOT_EMPTY( val ) TEMP_IS_NOT_EMPTY_IMPL(TEMP_ARGS_DUMMY( val ))
// [...]
#define ENUM_TYPE(type_) type_ // MAKE_ENUM will only return type_ if it exists
#if TEMP_IS_NOT_EMPTY( MAKE_ENUM ) == 1
typedef MAKE_ENUM EnumType;
#else
typedef int EnumType;
#endif
// [...]
问题是,
TEMP_IS_NOT_EMPTY
宏似乎只适用于 Clang,但不适用于 GCC。你知道为什么吗?还有可行的解决方法吗?
为了澄清问题,我在代码中添加了一个测试:
#define MAKE_ENUM_EMPTY
#if TEMP_IS_NOT_EMPTY( MAKE_ENUM_EMPTY ) == 1
// NOT empty
#warning "TEMP_IS_NOT_EMPTY does not work correctly for empty macro"
#else
// empty
#endif
#define MAKE_ENUM_NOT_EMPTY unsigned int
#if TEMP_IS_NOT_EMPTY( MAKE_ENUM_NOT_EMPTY ) == 1
// NOT empty
#else
// empty
#warning "TEMP_IS_NOT_EMPTY does not work correctly for NOT empty macro"
#endif
使用 GCC,我收到警告消息:
#warning "TEMP_IS_NOT_EMPTY does not work correctly for empty macro"
干杯!
我不喜欢“检查是否为空”。用宏很难做到。相反,应根据参数数量重载宏。我推荐以下模式:
#define ENUM_TYPE_1(name) ENUM_TYPE_2(name, int)
#define ENUM_TYPE_2(name, type) typedef type name;
#define ENUM_TYPE_N(_2,_1,N,...) ENUM_TYPE##N
#define ENUM_TYPE(...) ENUM_TYPE_N(__VA_ARGS__,_2,_1)(__VA_ARGS_)