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

使用可变参数和后期扩展创建字符串化宏参数的列表

发布时间:2020-12-16 07:07:09 所属栏目:百科 来源:网络整理
导读:我有以下问题 – 给出可变数量的宏参数argX来创建一个字符串化参数列表#argX 例: LIST(A,B) - "A","B"LIST(A,B,C) - "A","B","C" 我正在使用Boost,因此上面的宏对于每个参数数量使用辅助宏并将LIST(…)分派给适当的LIST_n(arg1,… argn)并不太难实现. 当LIS
我有以下问题 – 给出可变数量的宏参数argX来创建一个字符串化参数列表#argX

例:

LIST(A,B) -> "A","B"
LIST(A,B,C) -> "A","B","C"

我正在使用Boost,因此上面的宏对于每个参数数量使用辅助宏并将LIST(…)分派给适当的LIST_n(arg1,… argn)并不太难实现.

当LIST的输入本身是宏时,问题就开始了.在这种情况下(如果我使用…和__VA_ARGS__),宏会在字符串化之前展开,给出:

#define A 10
LIST(A,B) -> "10","B"

我希望这可以使用Windows标头中定义的宏,并且大多数值都有宏(MB_OK,AF_INET,…),所以我得到的是一个字符串化数字列表.

不使用__VA_ARGS__时一切正常:

#define A 10
#define LIST_1(arg0) #arg0
LIST_1(A) -> "A"

我已经尝试了几个宏将__VA_ARGS__的扩展推迟到以后的时间(例如,直到LIST_1,没有可变参数),但没有任何效果.

这甚至可以使用C预处理器实现吗?

解决方法

对不起,但现在有办法在msvc上这样做.由于预处理器中的经典错误(参见 here和 here),因此将__VA_ARGS__视为单个参数.要将其分解为单独的参数,需要应用另一个扫描,然后将扩展宏.在C99预处理器上,您可以使用空占位符禁止__VA_ARGS__的扩展:

/* This counts the number of args */
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__,8,7,6,5,4,3,2,1)

/* This will let macros expand before concating them */
#define PRIMITIVE_CAT(x,y) x ## y
#define CAT(x,y) PRIMITIVE_CAT(x,y)

/* p is an empty placeholder used to inhibit the expansion of __VA_ARGS__ */
#define STRINGIZE_ALL(p,...) FIRST(NARGS(__VA_ARGS__),PRIMITIVE_STRINGIZE_ALL(p ## __VA_ARGS__,~,~))
#define PRIMITIVE_STRINGIZE_ALL(x1,x2,x3,x4,x5,x6,x7,x8,...)  #x1,#x2,#x3,#x4,#x5,#x6,#x7,#x8

/* Retrieve the first n arguments from __VA_ARGS__ */
#define FIRST(n,...) CAT(FIRST_,n)(__VA_ARGS__,~)
#define FIRST_1(x1,...) x1
#define FIRST_2(x1,...) x1,x2
#define FIRST_3(x1,x3
#define FIRST_4(x1,x4
#define FIRST_5(x1,x5
#define FIRST_6(x1,x6
#define FIRST_7(x1,x7
#define FIRST_8(x1,x8

#define A 10
STRINGIZE_ALL(,A,B)

这将适用于gcc和clang 3.4或更高版本的最多8个参数.

(编辑:李大同)

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

    推荐文章
      热点阅读