如何在C++中使用__VA_ARGS__实现代码重复执行?
问题描述
我想在C++中创建这样的宏:
#define SETUP_BULK(...) \ SETUP_HELPER(__VA_ARG__) \ // 对所有__VA_ARGS__重复此操作
能不能实现?我查过遍历__VA_ARGS__的相关内容但没找到结果。我只能用宏实现,不然就违背了我的目标——通过自定义JSON解析器动态初始化结构体。
示例:
调用SETUP_BULK(Struct_A, Struct_B, Struct_C)
希望展开成:
SETUP_HELPER(Struct_A); SETUP_HELPER(Struct_B); SETUP_HELPER(Struct_C);
解决方案
可以实现,核心是利用预处理器的可变参数展开特性,结合辅助宏逐个处理每个参数。下面提供两种实用的实现方式:
方式1:递归宏拆解(兼容C++11及以上)
通过递归辅助宏逐步拆分参数列表,直到所有参数都被处理:
// 递归终止的空宏 #define SETUP_HELPER_END() // 处理单个参数,然后递归处理剩余参数 #define SETUP_HELPER_NEXT(arg, ...) \ SETUP_HELPER(arg); \ SETUP_BULK(__VA_ARGS__) // 主宏:根据参数数量选择调用递归宏还是终止宏 #define SETUP_BULK(...) \ _SETUP_BULK_CHOOSER(__VA_ARGS__, SETUP_HELPER_NEXT, SETUP_HELPER_END)(__VA_ARGS__) // 辅助选择宏:利用预处理器参数匹配特性,自动选择对应的处理逻辑 #define _SETUP_BULK_CHOOSER(a1, a2, func, ...) func
调用SETUP_BULK(Struct_A, Struct_B, Struct_C)时,会逐层展开:
- 首次展开触发
SETUP_HELPER_NEXT,生成SETUP_HELPER(Struct_A); SETUP_BULK(Struct_B, Struct_C) - 重复上述过程,直到参数耗尽,最终得到目标代码。
方式2:逗号展开式实现(更简洁)
借助数组初始化的逗号表达式特性,一次性展开所有参数:
// 辅助宏:把单个参数包装成SETUP_HELPER调用 #define _SETUP_WRAP(arg) SETUP_HELPER(arg); // 主宏:用数组初始化触发所有参数的展开 #define SETUP_BULK(...) \ do { \ int dummy[] = { 0, (_SETUP_WRAP(__VA_ARGS__), 0)... }; \ (void)dummy; /* 消除未使用变量的编译警告 */ \ } while(0)
原理说明:
(_SETUP_WRAP(__VA_ARGS__), 0)...会将每个参数展开为(SETUP_HELPER(Struct_A);, 0)这类表达式- 数组初始化时会依次执行这些表达式,从而生成所有需要的
SETUP_HELPER调用 do-while(0)是为了保证宏在任何代码语境下都能正确工作(比如放在if分支中不会出现语法错误)
这种方式需要编译器支持C++11的可变参数展开,现代主流编译器(GCC、Clang、MSVC)都能支持。
内容的提问来源于stack exchange,提问作者mineblock11
相关产品推荐
相关产品推荐

