我正在try 构建一个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

// [...]

The issue is that it seems the 100 macro only works with Clang but not GCC. Do you have any idea why? And would there be a viable workaround?

为了澄清这个问题,我用代码添加了一个测试:

#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_NAME  LanguageId
#define ENUM_TYPE  unsigned int
#define ENUM_FIELDS \
  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"

然后:

// "GenericToolbox.MakeEnum.h"
#ifndef ENUM_TYPE
// default:
#define ENUM_TYPE int
#endif
typedef ENUM_TYPE ENUM_NAME;
// process ENUM_FIELDS ...
#undef ENUM_TYPE
#undef ENUM_FIELDS
#undef ENUM_NAME

有趣的事实:这就是STC library正在使用的设计.

C++相关问答推荐

修改pGM使用指针填充2-D数组但不起作用

如何启用ss(另一个调查套接字的实用程序)来查看Linux主机上加入的多播组IP地址?

C中出现分段错误后关闭文件

如何在C中只使用一个带双方括号([i][j])访问语法的malloc来分配动态大小的2d数组?

括号中的堆栈实现错误问题

Malloc(sizeof(char[Length]))是否不正确?

GCC引发不明确的诊断消息

C是否用0填充多维数组的其余部分?

如何在c++中包装返回空*的函数

致命:ThreadSaniizer:在Linux内核6.6+上运行时意外的内存映射

`#if`条件中是否允许`sizeof`?

Vcpkg的配置文件

如何计算打印二叉搜索树时每行所需的空间?

在移动数组元素时获得意外输出

当b是无符号字符时,int a=(b<;<;2)>;>;2;和int a=b&;0x3F;之间有什么区别?

正数之和是负数

如何在VSCode中创建和使用我自己的C库?

我应该在递归中使用全局变量吗

在文件描述符上设置FD_CLOEXEC与将其传递给POSIX_SPOWN_FILE_ACTIONS_ADCLOSE有区别吗?

为什么孤儿进程在 Linux 中没有被 PID 1 采用,就像我读过的一本书中声称的那样?