学习boost预编译的代码

来源:互联网 发布:nginx 80端口被占用 编辑:程序博客网 时间:2024/06/05 10:44

boost的代码很难看懂,从今天起每天看一点。

【1】在通过编译前,查看宏置换的结果,即方便解决编译问题,又方便分析代码,方法如下

#define STR(a) STR_I(a)
#define STR_I(a) #a

printf(STR(SOME_MARCO(xxx)));

再用此方法看看最难懂的宏之一 BOOST_PP_AUTO_REC的置换结果(注意包含对应的头文件)

 printf(STR(BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4)));
 printf("\n");
 printf(STR(BOOST_PP_AUTO_REC(BOOST_PP_WHILE_P, 256)));
 printf("\n");
 printf(STR(BOOST_PP_AUTO_REC(BOOST_PP_FOR_P, 256)));
 printf("\n");
 printf(STR(BOOST_PP_AUTO_REC(BOOST_PP_SEQ_FOLD_LEFT_P, 256)));
 printf("\n");

打印出来的结果全是“1”,很意外,那么这个宏到底起什么作用呢?

猜测1:对输入的第一个参数进行校验,确定是有效的宏,避免编译器进入死循环什么的

猜测2:提高编译速度,减少宏置换时的递归深度

 

【2】BOOST_PP_WHILE宏的作用

BOOST_PP_WHILE 被置换成BOOST_PP_WHILE_1,看代码从这里看起,不要管那个BOOST_PP_AUTO_REC(BOOST_PP_WHILE_P, 256)
该宏需要三个参数,第一个是被称为pred的宏,负责生成循环结束条件;第二个是被称为op的宏,就是每次循环要执行的操作;第三个是被操

作的参数,格式为(a,b,c,d)中间可以有任意个元素,在boost中这种格式被称为tuple;该宏的返回值也是一个tuple。
宏pred和宏op都是调用者实现的,其格式有严格的要求。
pred的格式为MARCO_NAME(d,xy),参数d是循环执行次数的序号,起始序号为2;参数xy是一个tuple,其长度和WHILE宏的第三个参数相等;要

求返回一个整数,返回0时终止循环,返回1~256时的效果是一样的,都是继续循环。
op的格式为MARCO_NAME(d,xy),参数d是循环执行次数的序号;参数xy是一个tuple,长度和WHILE宏的第三个参数相等;要求返回一个tuple,

长度为WHILE宏的第三个参数相等。
以加法操作BOOST_PP_ADD(x,y)为例,首先生成长度为2的tuple(x,y),然后执行
BOOST_PP_WHILE( BOOST_PP_ADD_P, BOOST_PP_ADD_O, (x,y) )
宏BOOST_PP_ADD_P构造循环终止条件,简单地返回y的值
宏BOOST_PP_ADD_O将输入的(x,y)变成(x+1,y-1)
没循环一次,x的值加1,y的值减1,y变成零时结束循环,此时x变成x+y了,WHILE宏返回的结果是(x+y,0)

 

【3】BOOST_PP_WHILE的实现原理

# define BOOST_PP_WHILE_2(p, o, s) BOOST_PP_WHILE_2_C(BOOST_PP_BOOL(p(3, s)), p, o, s)
# define BOOST_PP_WHILE_2_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_3, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o,

BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(3, s))

BOOST_PP_IIF是条件判定分支,BOOST_PP_IF(c, A, B)在c不为0是返回A,在c为0是返回B,变成下面样子
# define BOOST_PP_WHILE_2_C(c, p, o, s)
  if (c)
    BOOST_PP_WHILE_3(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(3, s))
  else  
    s BOOST_PP_TUPLE_EAT_3(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(3, s))

BOOST_PP_TUPLE_EAT_3的作用就是消掉输入的三个参数,变成下面样子
# define BOOST_PP_WHILE_2_C(c, p, o, s)
  if (c)
    BOOST_PP_WHILE_3(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(3, s))
  else  
    s

上面if (c) 分支中,还有一个BOOST_PP_IF判断,判定结果肯定是true,变成下面样子
# define BOOST_PP_WHILE_2_C(c, p, o, s)
  if (c)
    BOOST_PP_WHILE_3(p, o, o(3, s))
  else
    s

综合起来,变成下面简单的形式
#define BOOST_PP_WHILE_2(p, o, s)
  IF p(3,s)
     BOOST_PP_WHILE_3(p, o, o(3,s))
  ELSE
     s

为什么不用递归的方式,而是写一大堆的BOOS_PP_WHILE_n?应该是怕递归不能正确地结束,编译时使编译器进入死循环。

 

 

原创粉丝点击