加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 10:06:50 所属栏目:百科 来源:网络整理
导读:我想为可变参数宏中的每个元素追加一个字符串化的宏参数.我想我知道我需要什么,但我还没有想出一个有效的解决方案.给出一个可变宏,如: #define FIELD_DECLARATION(NAME,OTHER_FIELD,...)FIELD_DECLARATION(First,Thing)FIELD_DECLARATION(Second,Thing,Noth
我想为可变参数宏中的每个元素追加一个字符串化的宏参数.我想我知道我需要什么,但我还没有想出一个有效的解决方案.给出一个可变宏,如:

#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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读