预处理器:将字符串连接到__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中使用。
演示,原始代码
演示,当前代码