预处理器:将字符串连接到__VA_ARGS__中的每个参数

我想将一个字符串化的宏参数附加到可变参数宏中的每个元素。 我想我知道我需要什么,但我还没有想出一个有效的解决方案。 鉴于可变宏,如:

#define FIELD_DECLARATION(NAME, OTHER_FIELD, ...) FIELD_DECLARATION(First, Thing) FIELD_DECLARATION(Second, Thing, Thing, Nothing) 

我想生成:

 field_First = {ThingArg}; field_Second = {ThingArg, ThingArg, NothingArg}; 

我想我需要的是递归地继续扩展__VA_ARGS__直到它没有元素,并在进行扩展时附加"Arg" 。 最后,将结果传递给另一个可变参数宏,该宏生成以逗号分隔的参数列表。

我试过这个,这是行不通的(也不是我所描述的):

 #define UNPACK_VA_1(A1) A1 ## Arg #define UNPACK_VA_2(A1, A2) UNPACK_VA_1(A1), UNPACK_VA_1(A2) #define UNPACK_VA_3(A1, A2, A3) UNPACK_VA_2(A1, A2), UNPACK_VA_1(A3) #define UNPACK_VA_4(A1, A2, A3, A4) UNPACK_VA_2(A1, A2), UNPACK_VA_2(A3, A4) #define UNPACK_VA(...) UNPACK_VA_4(__VA_ARGS__) #define FOO(x, y, ...) UNPACK_VA(__VA_ARGS__) FOO(One, Two, Three, Four, Five, Six) 

虽然这有点奏效,但我无法提出可扩展的解决方案。 如果有人可以发光,那就太棒了。

这是一种可扩展的方法。 首先,一些通用实用程序宏:

 #define EVAL(...) __VA_ARGS__ #define VARCOUNT(...) \ EVAL(VARCOUNT_I(__VA_ARGS__,9,8,7,6,5,4,3,2,1,)) #define VARCOUNT_I(_,_9,_8,_7,_6,_5,_4,_3,_2,X_,...) X_ #define GLUE(X,Y) GLUE_I(X,Y) #define GLUE_I(X,Y) X##Y #define FIRST(...) EVAL(FIRST_I(__VA_ARGS__,)) #define FIRST_I(X,...) X #define TUPLE_TAIL(...) EVAL(TUPLE_TAIL_I(__VA_ARGS__)) #define TUPLE_TAIL_I(X,...) (__VA_ARGS__) #define TRANSFORM(NAME_, ARGS_) (GLUE(TRANSFORM_,VARCOUNT ARGS_)(NAME_, ARGS_)) #define TRANSFORM_1(NAME_, ARGS_) NAME_ ARGS_ #define TRANSFORM_2(NAME_, ARGS_) NAME_(FIRST ARGS_),TRANSFORM_1(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_3(NAME_, ARGS_) NAME_(FIRST ARGS_),TRANSFORM_2(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_4(NAME_, ARGS_) NAME_(FIRST ARGS_),TRANSFORM_3(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_5(NAME_, ARGS_) NAME_(FIRST ARGS_),TRANSFORM_4(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_6(NAME_, ARGS_) NAME_(FIRST ARGS_),TRANSFORM_5(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_7(NAME_, ARGS_) NAME_(FIRST ARGS_),TRANSFORM_6(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_8(NAME_, ARGS_) NAME_(FIRST ARGS_),TRANSFORM_7(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_9(NAME_, ARGS_) NAME_(FIRST ARGS_),TRANSFORM_8(NAME_,TUPLE_TAIL ARGS_) 

在语义上, VARCOUNT计算参数; GLUE是典型的间接贴纸; FIRST提取第一个参数; EVAL扩展为其参数(意图评估), TUPLE_TAIL返回元组的尾部(即,它丢弃第一个参数)。

TRANSFORM这里是主要的想法; TRANSFORM(FOO,(X,Y,Z))将元组(X,Y,Z)(FOO(X),FOO(Y),FOO(Z))

这就到位了,这是特殊用途代码:

 #define Z_ARG(X) GLUE(X,Arg) #define MAKE_INITIALIZER(...) { __VA_ARGS__ } #define FIELD_DECLARATION(FNAME_, ...) \ GLUE(field_, FNAME_) = EVAL(MAKE_INITIALIZER TRANSFORM(Z_ARG, (__VA_ARGS__))); 

鉴于上述情况,这应该是可读的,但只是为了解释…… Z_ARG Arg粘贴到一个项目; MAKE_INITIALIZER将预处理器元组转换为初始化列表; 和FIELD_DECLARATION是你的宏。 请注意, EVAL包装MAKE_INITIALIZER /转换后的元组,因此它实际上会调用该宏。

注意:将EVAL移到顶部并在更多位置使用它,这样它也可以在MSVC中使用。

演示,原始代码

演示,当前代码