如何让支持多参数的EXPAND_FUNC宏兼容空参数场景?
问题:让EXPAND_FUNC宏支持空参数场景
我需要一个可根据参数生成函数的宏,例如调用EXPAND_FUNC(func, int)时,生成如下函数:
void func(int a) { _func(a); }
现有实现代码如下:
#define CONCAT_(a, b) a##b #define CONCAT(a, b) CONCAT_(a, b) #define EXPAND(x) x #define ARG_N(...) EXPAND(NARG(__VA_ARGS__, RSEQN())) #define NARG(...) EXPAND(ARG_N_(__VA_ARGS__)) #define ARG_N_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N #define RSEQN() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 #define GET_MACRO(func, ...) CONCAT(func, EXPAND(ARG_N(__VA_ARGS__))) #define COMPOSE(name, ...) EXPAND(name(__VA_ARGS__)) #define PARAMS(...) COMPOSE(GET_MACRO(PARAMS_, __VA_ARGS__), __VA_ARGS__) #define PARAMS_0() #define PARAMS_1(A) A a #define PARAMS_2(A, B) A a, B b #define PARAMS_3(A, B, C) A a, B b, C c #define PARAMS_4(A, B, C, D) A a, B b, C c, D d #define PARAMS_5(A, B, C, D, E) A a, B b, C c, D d, E e #define PARAMS_6(A, B, C, D, E, F) A a, B b, C c, D d, E e, F f #define ARGS(...) COMPOSE(GET_MACRO(ARGS_, __VA_ARGS__), __VA_ARGS__) #define ARGS_0() #define ARGS_1(A) a #define ARGS_2(A, B) a, b #define ARGS_3(A, B, C) a, b, c #define ARGS_4(A, B, C, D) a, b, c, d #define ARGS_5(A, B, C, D, E) a, b, c, d, e #define ARGS_6(A, B, C, D, E, F) a, b, c, d, e, f #define EXPAND_FUNC(name, ...) \ void name(PARAMS(__VA_ARGS__)) \ { \ _##name(ARGS(__VA_ARGS__));\ }
当前EXPAND_FUNC宏支持一个或多个参数,但无法处理空参数场景。调用EXPAND_FUNC(func0)时,会错误展开为:
void func0(a) { _func0(a); }
请问如何修改才能让EXPAND_FUNC(func0)正常工作?
解决方案
问题根源
当__VA_ARGS__为空时,原有参数计数宏会错误地将其识别为1个空参数,导致调用PARAMS_1()和ARGS_1(),最终展开出无效的a标识符。
修改方案
新增空参数判断逻辑,让计数宏在__VA_ARGS__为空时返回0,从而正确调用PARAMS_0()和ARGS_0()。
修改后的完整代码
#define CONCAT_(a, b) a##b #define CONCAT(a, b) CONCAT_(a, b) #define EXPAND(x) x // 判断可变参数是否为空 #define HAS_ARGS(...) EXPAND(HAS_ARGS_(__VA_ARGS__, 1, 0)) #define HAS_ARGS_(_1, _2, ...) _2 // 条件选择辅助宏 #define IF(cond, then, else) CONCAT(IF_, cond)(then, else) #define IF_1(then, else) then #define IF_0(then, else) else // 修正参数计数:空参数返回0,非空返回实际参数个数 #define ARG_N(...) \ EXPAND(IF(HAS_ARGS(__VA_ARGS__), NARG(__VA_ARGS__, RSEQN()), 0)) #define NARG(...) EXPAND(ARG_N_(__VA_ARGS__)) #define ARG_N_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N #define RSEQN() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 #define GET_MACRO(func, ...) CONCAT(func, EXPAND(ARG_N(__VA_ARGS__))) #define COMPOSE(name, ...) EXPAND(name(__VA_ARGS__)) #define PARAMS(...) COMPOSE(GET_MACRO(PARAMS_, __VA_ARGS__), __VA_ARGS__) #define PARAMS_0() #define PARAMS_1(A) A a #define PARAMS_2(A, B) A a, B b #define PARAMS_3(A, B, C) A a, B b, C c #define PARAMS_4(A, B, C, D) A a, B b, C c, D d #define PARAMS_5(A, B, C, D, E) A a, B b, C c, D d, E e #define PARAMS_6(A, B, C, D, E, F) A a, B b, C c, D d, E e, F f #define ARGS(...) COMPOSE(GET_MACRO(ARGS_, __VA_ARGS__), __VA_ARGS__) #define ARGS_0() #define ARGS_1(A) a #define ARGS_2(A, B) a, b #define ARGS_3(A, B, C) a, b, c #define ARGS_4(A, B, C, D) a, b, c, d #define ARGS_5(A, B, C, D, E) a, b, c, d, e #define ARGS_6(A, B, C, D, E, F) a, b, c, d, e, f #define EXPAND_FUNC(name, ...) \ void name(PARAMS(__VA_ARGS__)) \ { \ _##name(ARGS(__VA_ARGS__));\ }
效果验证
- 调用
EXPAND_FUNC(func0)时,生成正确的无参函数:void func0() { _func0(); } - 调用
EXPAND_FUNC(func, int)时,依然正常生成单参数函数:void func(int a) { _func(a); }
内容的提问来源于stack exchange,提问作者user28234794
相关产品推荐
相关产品推荐

