如何实现__VA_OPT__反向效果?C预处理器可选参数默认值方案
实现__VA_ARGS__为空时展开默认内容的方案
要实现你需要的效果——调用MY_MACRO()时展开为default,调用MY_MACRO(arg)时展开为arg,可以借助C20标准的__VA_OPT__特性来完成,这是目前最可靠的方案。
C20 实现方案
利用__VA_OPT__在可变参数非空时生成特定标记,通过宏的条件展开实现逻辑:
#define MY_MACRO(...) \ __VA_OPT__(__VA_ARGS__) \ _DEFAULT_##__VA_OPT__(NON_EMPTY) // 当传入参数时,此宏展开为空 #define _DEFAULT_NON_EMPTY // 当无参数时,此宏展开为默认值 #define _DEFAULT default
工作原理
- 调用
MY_MACRO()时,__VA_ARGS__为空,__VA_OPT__(NON_EMPTY)展开为空,因此_DEFAULT_##__VA_OPT__(NON_EMPTY)会被替换为_DEFAULT,最终结果为default。 - 调用
MY_MACRO(arg)时,__VA_ARGS__非空,__VA_OPT__(NON_EMPTY)展开为NON_EMPTY,_DEFAULT_NON_EMPTY为空,最终结果为arg。
通用版__VA_NOT_OPT__模拟
如果你想封装一个通用的__VA_NOT_OPT__宏(仅当__VA_ARGS__为空时展开指定内容),可以这样实现:
#define _SELECT(_, EMPTY_RES, NON_EMPTY_RES, ...) EMPTY_RES #define __VA_NOT_OPT__(content) \ _SELECT(__VA_OPT__(,), content, /* 非空时无输出 */)
使用时直接按你示例中的方式写:
#define MY_MACRO(...) __VA_NOT_OPT__(default) __VA_ARGS__
传统预处理器方案(无C20支持)
如果编译器不支持C20,传统预处理器技巧无法完美区分“无参数”和“传递空参数”,但可以在特定场景下使用:
#define _GET_FIRST(_1, _2) _1 #define MY_MACRO(...) _GET_FIRST(__VA_ARGS__, default)
注意:这种方法有缺陷——调用MY_MACRO()时,__VA_ARGS__为空,_GET_FIRST会返回空参数而非default,仅在你能确保调用时始终传递参数,或者接受用MY_MACRO(())触发默认值时才适用。
内容的提问来源于stack exchange,提问作者Martin Fehrs
相关产品推荐
相关产品推荐

