预处理器:将字符串连接到__VA_ARGS__中的每个参数
我想为可变参数宏中的每个元素追加一个字符串化的宏参数.我想我知道我需要什么,但我还没有想出一个有效的解决方案.给出一个可变宏,如:
#define FIELD_DECLARATION(NAME,OTHER_FIELD,...) FIELD_DECLARATION(First,Thing) FIELD_DECLARATION(Second,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,A3,A4) UNPACK_VA_2(A1,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_,TRANSFORM_2(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_4(NAME_,TRANSFORM_3(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_5(NAME_,TRANSFORM_4(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_6(NAME_,TRANSFORM_5(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_7(NAME_,TRANSFORM_6(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_8(NAME_,TRANSFORM_7(NAME_,TUPLE_TAIL ARGS_) #define TRANSFORM_9(NAME_,TRANSFORM_8(NAME_,TUPLE_TAIL ARGS_) 在语义上,VARCOUNT计算参数; GLUE是典型的间接贴纸; FIRST提取第一个参数; EVAL扩展为其参数(意图评估),并且TUPLE_TAIL返回元组的尾部(即,它丢弃第一个参数). 转换这里是主要的想法; TRANSFORM(FOO,(X,Y,Z))将元组(X,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中使用. Demonstration,original code Demonstration,current code (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |