学习boost预编译的代码:BOOST_PP_IS_EMPTY(X)

 BOOST_PP_IS_EMPTY(X)
这个宏判断输入参数X是否为空,例如 #define X 就定义了一个空的X,而 #define X 80 就不是空的。
为了方便,将BOOST_PP_IS_EMPTY_DEF_简称为DEF_,将BOOST_PP_IS_EMPTY_HELPER简称为HELP。
实现原理,将DEF_ X 空格 HELP 用##连接在一起。如果X为空,编译器会剔除掉空格,连接结果为DEF_HELP;如果X

不为空,连接结果为DEF_X HELP;这样就区分开了。为了返回1或0,将DEF_HELP定义成 _,1,将HELP定义成 ,0。这

样当X为空时得到 _,1,否则得到DEF_X,0,再用一个宏取出第二个逗号后面的数字。其中下划线也是一个合法的变量

名,通常用于那些被忽略的参数。
但是,上面方法在VC++上行不通,它没有把空格剔除干净,当X为空时,得到DEF_ 空格 HELP。
解决方法,先将HELP 空格 X()连接在一起,如果X为空格,得到HELP 空格 (),否则得到HELP 空格 X()。再定义

#define HELP() 1,注意HELP后面的括号不能省掉,这样HELP 空格 ()被替换成1,而HELP 空格 X()不满足替换条件

。再将DEF_和前面的结果连接在一起,X为空时得到DEF_1,否则得到DEF_HELP X(),定义#define DEF_1 1,_,定义

#define DEF_HELP 0,(注意0后面的逗号)。最终,X为空时得到1,_ 否则得到0,X(),用一个宏取出逗号前面的数字。
从原理到实现,还有很关键的东西,就是控制宏替换的过程
首先实现第一个原理,没有验证环境
#define EMPTY(x)  EMPTY_I(x HELP)
#define EMPTY_I(c) GET_SECOND( DEF_ ## c()) 这一步让编译器对x HELP进行置换,剔除空格
#define DEF_HELP _,1
#define HELP()  ,0 注意HELP后面要有括号,否则置换x HELP就被置换了
再实现第二个原理,在VC7上验证
#define EMPTY(x) EMPTY_I(HELP x())
#define EMPTY_I(c) CAT(DEF_,c) 这一步让编译器对HELP x()进行置换
#define CAT(a,b) CAT_I(a ## b)
#define CAT_I(a) a 这一步让编译器对DEF_1,或DEF_HELP x()进行置换
#define DEF_1  1,_
#define DEF_HELP 0,
#define HELP()  1

来验证一下
#define M
#define N 80
printf(STR( EMPTY(M) ));
printf(STR( EMPTY(N) ));
得到的结果为 1,_ 和 0, 80() ,很好,是想要的结果。

接下来加上获取逗号前面元素的宏
#define GET_FIRST(a,b) a
#define EMPTY_RES(x) GET_FIRST( EMPTY(x) )
在验证一下,输出结果还是 1,_ 和0, 80() ,没有按设想地返回逗号前面的数,怎么回事!!
编译过程出现了警告:warning C4003: not enough actual parameters for macro 'GET_FIRST'
编译器将EMPTY(x)返回的结果作为一个整体传给GET_FIRST的参数a了。

重新实现一下GET_FIRST,注意学了,高级技巧
#define GET_FIRST(a) GET_FIRST_I ( (a) ) 在两边加上括号,变成 (1,_)
#define GET_FIRST_I(a) GET_FIRST_III (GET_FIRST_II ## a) 连接得到 GET_FIRST_II (1,_)
#define GET_FIRST_II(a,b) a
#define GET_FIRST_III(a)  a 如果没有这个宏,编译器不会置换GET_FIRST_II (1,_),而是原样返回

用同样的方法,可以实现支持输入任意个数参数的宏,参数n表示输入参数个数
#define M(n , ...)   M_1(n, (__VA_ARGS__))
#define M_1(n, data) M_3 ( MM_ ## n ## data )
#define M_3(a)       a
#define MM_1(a)
#define MM_2(a,b)
#define MM_3(a,b,c)
#define MM_4(a,b,c,d) 可以实现成任意形式

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值