C++技巧

http://blog.csdn.net/maray/article/details/11096459

你能实现这样一个函数吗:

[cpp]  view plain  copy
  1.   MyType type;  
  2.   HisType htype;  
  3.   serialize_3(11, type, htype);  
  4.   serialize_4(type, htype ,type, htype);  
  5.   serialize_4(11, type , htype, htype);  
参数类型自由,个数自由,怎么做呢?往下看:


[cpp]  view plain  copy
  1. [xiaochu.yh@OB macro]$ cat auto_type.cpp   
  2. /* 
  3.  * (C) 1999-2013 Alibaba Inc. 
  4.  * 
  5.  * This program is free software; you can redistribute it and/or modify 
  6.  * it under the terms of the GNU General Public License version 2 as 
  7.  * published by the Free Software Foundation. 
  8.  * 
  9.  * 
  10.  * Version:  auto_type.cpp,  09/04/2013 08:02:17 PM Yu Huang Exp $ 
  11.  * 
  12.  * Author: 
  13.  *   Huang Yu <xiaochu.yh@alipay.com> 
  14.  * Description: 
  15.  *   auto type match 
  16.  * 
  17.  */  
  18.   
  19. #include <stdio.h>  
  20.   
  21. void serialize()  
  22. {  
  23.   return;  
  24. }  
  25.   
  26. class HisType  
  27. {  
  28.   public:  
  29.     HisType(const char *i) : value_(i) { }  
  30.     ~HisType() { }  
  31.     void serialize() const  
  32.     {  
  33.       printf("HisType: s(%s)\n", value_);  
  34.     }  
  35.   private:  
  36.     const char *value_;  
  37. };  
  38.   
  39. class MyType  
  40. {  
  41.   public:  
  42.     MyType(int i) : value_(i) { }  
  43.     ~MyType() { }  
  44.     void serialize() const  
  45.     {  
  46.       printf("MyType: f(%d)\n", value_);  
  47.     }  
  48.   private:  
  49.     int value_;  
  50. };  
  51.   
  52. void serialize(const int arg0)  
  53. {  
  54.   printf("int: %d\n", arg0);  
  55. }  
  56. void serialize(const float arg0)  
  57. {  
  58.   printf("float: %f\n", arg0);  
  59. }  
  60.   
  61. template<typename Arg0>  
  62. void serialize(const Arg0 &arg0)  
  63. {  
  64.   arg0.serialize();  
  65. }  
  66.   
  67. template<typename Arg0>  
  68. void serialize_1(const Arg0 &arg0)  
  69. {  
  70.   serialize(arg0);  
  71. }  
  72.   
  73. #define JOIN(x,y) JOIN2(x,y)  
  74. #define JOIN2(x,y) x##y  
  75.   
  76. #define DECVAL_1 0  
  77. #define DECVAL_2 1  
  78. #define DECVAL_3 2  
  79. #define DECVAL_4 3  
  80. #define DEC_VAL(n) DECVAL_##n  
  81.   
  82. // recursively expanding macro  
  83. #define ARG_TN0  
  84. #define ARG_TN1  typename Arg0  
  85. #define ARG_TN2  ARG_TN1, typename Arg1  
  86. #define ARG_TN3  ARG_TN2, typename Arg2  
  87. #define ARG_TN4  ARG_TN3, typename Arg3  
  88.   
  89. #define ARG_PN0  
  90. #define ARG_PN1  const Arg0 & arg0  
  91. #define ARG_PN2  ARG_PN1, const Arg1 & arg1  
  92. #define ARG_PN3  ARG_PN2, const Arg2 & arg2  
  93. #define ARG_PN4  ARG_PN3, const Arg3 & arg3  
  94.   
  95. #define ARG_AN0  
  96. #define ARG_AN1  arg0  
  97. #define ARG_AN2  ARG_AN1, arg1  
  98. #define ARG_AN3  ARG_AN2, arg2  
  99. #define ARG_AN4  ARG_AN3, arg3  
  100.   
  101.   
  102. #define ARG_CN0  
  103. #define ARG_CN1  arg0  
  104. #define ARG_CN2  arg1  
  105. #define ARG_CN3  arg2  
  106. #define ARG_CN4  arg3  
  107.   
  108.   
  109. #define SERIALIZE_DECLARE(NUM_ARG) \  
  110.   template<JOIN(ARG_TN, NUM_ARG)> \  
  111. void JOIN(serialize_, NUM_ARG)(JOIN(ARG_PN, NUM_ARG))  
  112.   
  113. SERIALIZE_DECLARE(2);  
  114. SERIALIZE_DECLARE(3);  
  115. SERIALIZE_DECLARE(4);  
  116. #define SERIALIZE_DEFINE(NUM_ARG) \  
  117.   template<JOIN(ARG_TN, NUM_ARG)> \  
  118. void JOIN(serialize_, NUM_ARG)(JOIN(ARG_PN, NUM_ARG)) \  
  119. { \  
  120.   JOIN(serialize_, DEC_VAL(NUM_ARG))(JOIN(ARG_AN, DEC_VAL(NUM_ARG))); \  
  121.   serialize(JOIN(ARG_CN, NUM_ARG)); \  
  122. }  
  123.   
  124.   
  125. SERIALIZE_DEFINE(2);  
  126. SERIALIZE_DEFINE(3);  
  127. SERIALIZE_DEFINE(4);  
  128.   
  129. int main()  
  130. {  
  131.   MyType type(4234);  
  132.   HisType htype("home");  
  133.   //先来个见面礼, 1是int类型,10.2f是float类型,type是自定义类型  
  134.   serialize_4(1,10.2f,3, type);  
  135.   printf("==============\n");  
  136.   serialize_3(type,11, htype);  // <== 注意下面的参数个数,以及参数顺序,完全自由!  
  137.   printf("==============\n");  
  138.   serialize_3(11 ,type, htype);  
  139.   printf("==============\n");  
  140.   serialize_3(htype ,type, htype);  
  141.   printf("==============\n");  
  142.   return 0;  
  143. }  

编译运行结果:

[cpp]  view plain  copy
  1. [xiaochu.yh@OB macro]$ g++ auto_type.cpp             
  2. [xiaochu.yh@OB]$ ./a.out   
  3. int: 1  
  4. float: 10.200000  
  5. int: 3  
  6. MyType: f(4234)  
  7. ==============  
  8. MyType: f(4234)  
  9. int: 11  
  10. HisType: s(home)  
  11. ==============  
  12. int: 11  
  13. MyType: f(4234)  
  14. HisType: s(home)  
  15. ==============  
  16. HisType: s(home)  
  17. MyType: f(4234)  
  18. HisType: s(home)  
  19. ==============  


该技术是从曲山同学的代码中学习来的,曲山对宏的运用真是炉火纯青!这里最神奇的就是下面一段代码,至今不明:

[cpp]  view plain  copy
  1. #define JOIN(x,y) JOIN2(x,y)  
  2. #define JOIN2(x,y) x##y  

JOIN和JOIN2不是等价的吗?不过还真不是。如果只写JOIN2,在宏展开阶段会有比较诡异的事情发生。不信你试试。但是为什么呢?我也不知道。@曲山,求助啊~~

更全面的代码见OceanBase源码oceanbase/src/common/ob_rpc_stub.h和oceanbase/src/common/ob_rpc_macros.h


=============================================

UPDATE:

这篇帖子发到了内网,得到了@探晴同学指点,加上@元启 同学的解释,基本弄明白了JOIN的机制。

原因的确很简单。 
#define MY_VALUE 2 
#define JOIN(A,B) A##B
JOIN(hello, world)的输出结果就是 helloworld,
JOIN(MY_VALUE, b)的输出结果就是 MY_VALUEb。尽管MY_VALUE是个宏,你期待它展开成2b。

如何成为一个2b呢? 这么做:
#define JOIN(a, b) JOIN_EXPAND_PARAM(a,b)
#define JOIN_EXPAND_PARAM(a,b) a##b

JOIN(MY_VALUE, b)的展开过程是:
1. JOIN(MY_VALUE, b)展开成 JOIN_EXPAND_PARAM(2, b)
2. JOIN_EXPAND_PARAM(2, b) 展开成 2b

这句话:Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringified or pasted with other tokens.

参考: http://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html



**=======UPDATE=========**




C++11中引入了可变长参数模板,不需要用上面这么丑的方法了。几句话就搞定,而且不用带上说明参数个数的数字了:


[cpp]  view plain  copy
  1. // filename:template.cpp  
  2.   
  3. #include <iostream>  
  4. using namespace std;  
  5.   
  6. template<typename T>  
  7. void serialize(T value)  
  8. {  
  9.     cout << value << endl;  
  10. }  
  11.   
  12. template <typename Head, typename... Rail>  
  13. void serialize(Head head, Rail... rail)  
  14. {     
  15.     cout << head << ",";  
  16.     serialize(rail...);  
  17. }  
  18.   
  19. int main(int argc, char *argv[])  
  20. {  
  21.     serialize(1);                  // 输出:1  
  22.     serialize(1, "hello");         // 输出:1,Hello  
  23.     serialize(1, "hello"'H');    // 输出:1,Hello,H  
  24.     return 0;  
  25. }  



编译的时候需要试用-std=c++0x或者 -std=gnu++0x


    g++ -std=c++0x template.cpp  -o template

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值