如何让宏为传入记号赋值并拼接?寻求宏生成器优化方案
问题:如何让宏为传入的记号提供值并展开拼接?
现有解决方案
当前通过定义模板宏+生成器宏的方式实现,但需要单独维护TEMPLATE_*系列宏,与实际使用的拼接模式脱节:
#define TEMPLATE_X_YX_(X, Y, a, b, c) a ## X ## b ## Y ## X ## c // 其他排列方式的模板宏需单独定义 #define GENERATOR(name, template, ...) \ const auto name##1 = &TEMPLATE##template(A, 1, __VA_ARGS__); \ const auto name##2 = &TEMPLATE##template(B, 2, __VA_ARGS__); \ const auto name##3 = &TEMPLATE##template(C, 3, __VA_ARGS__); GENERATOR(example, _X_YX_, example_, _mid_, _suffix) // 预期展开结果: // const auto example1 = &example_A_mid_1A_suffix; // const auto example2 = &example_B_mid_2B_suffix; // const auto example3 = &example_C_mid_3C_suffix;
痛点与期望写法
需要单独定义TEMPLATE_*宏,导致拼接模式与生成逻辑分离,期望直接在生成器中传入拼接模式,写法如下:
GENERATOR(example, example_, X, _mid_, Y, X, _suffix)
解决方案
通过预处理器的递归展开与占位符替换,实现直接传入模式片段的生成器,无需单独定义模板宏:
辅助宏实现
// 强制展开宏参数,解决递归展开延迟问题 #define EXPAND(...) __VA_ARGS__ // 处理单个模式片段:替换X/Y为对应值,其他片段直接保留 #define REPLACE_XY(X_val, Y_val, frag) \ _REPLACE_XY_##frag(X_val, Y_val) // X/Y占位符的替换分支 #define _REPLACE_XY_X(X_val, Y_val) X_val #define _REPLACE_XY_Y(X_val, Y_val) Y_val // 非X/Y片段的默认处理:直接保留原片段 #define _REPLACE_XY_default(X_val, Y_val, frag) frag #define _REPLACE_XY_frag(X_val, Y_val) _REPLACE_XY_default(X_val, Y_val, frag) // 递归遍历所有模式片段,逐个替换后拼接 #define APPLY_PATTERN(X_val, Y_val, ...) \ _APPLY_PATTERN(X_val, Y_val, __VA_ARGS__) #define _APPLY_PATTERN(X_val, Y_val, frag, ...) \ REPLACE_XY(X_val, Y_val, frag) \ _APPLY_PATTERN_NEXT(X_val, Y_val, __VA_ARGS__) #define _APPLY_PATTERN_NEXT(X_val, Y_val, ...) \ EXPAND(_APPLY_PATTERN(X_val, Y_val, __VA_ARGS__)) // 递归终止条件 #define _APPLY_PATTERN(X_val, Y_val)
生成器宏实现
#define GENERATOR(name, ...) \ const auto name##1 = &APPLY_PATTERN(A, 1, __VA_ARGS__); \ const auto name##2 = &APPLY_PATTERN(B, 2, __VA_ARGS__); \ const auto name##3 = &APPLY_PATTERN(C, 3, __VA_ARGS__);
使用示例
GENERATOR(example, example_, X, _mid_, Y, X, _suffix)
展开结果
const auto example1 = &example_A_mid_1A_suffix; const auto example2 = &example_B_mid_2B_suffix; const auto example3 = &example_C_mid_3C_suffix;
原理说明
REPLACE_XY宏识别模式中的X/Y占位符,替换为传入的实际值(如A/1),非占位符片段直接保留。APPLY_PATTERN通过递归遍历所有模式片段,将替换后的内容拼接成最终的函数名。EXPAND宏强制预处理器多执行一轮展开,确保递归拼接能完全生效。
扩展说明
- 若需要支持更多占位符(如
Z),只需新增对应的_REPLACE_XY_Z宏分支即可。 - 模式片段可以包含任意合法标识符,只要不与辅助宏的命名(如
_REPLACE_XY_开头)冲突即可。
内容的提问来源于stack exchange,提问作者sh1
相关产品推荐
相关产品推荐

