[C++ 2011 STL (VS2012 Update4) 源代码阅读系列(2)]熟悉一些宏定义和模版偏特化或叫模版专门化

// point_test.cpp : 知识点练习和测试,用于单步调试,跟踪。
//

#include "stdafx.h"
#include <functional>
#include <string>
#include <iostream>

using namespace std;
 //for _1, _2, _3...
using namespace std::placeholders;

template<class T1,class T2> const T1 my_strcat(const T1 &t1,const T2 &t2)
{
    return std::move(t1 + t2);
}

/*
测试例子演示了std::bind 和 std:function 的各种组合以及调用的方式
如果你的编译器编译失败,请尽可能的先去掉 const 后编译,如果全部去掉后
还是编译失败,请把你的编译器升级到最高版本或者换了它。
*/
void test_bind()
{
    std::string s1 = "aaa",s2 = "BBB",ss = "";
    ss = std::bind(my_strcat<std::string,std::string>,s1,s2)();
    std::cout<<ss<<endl;
    ss = my_strcat<std::string,std::string>(s1,s2);
    std::cout<<ss<<endl;
    std::function<const std::string (std::string,std::string)> f1 ;
    f1 = std::bind(my_strcat<std::string,std::string>,_1,_2);
    ss = f1(s1,s2);
    std::cout<<ss<<endl;
    std::function<std::string ()> f2;
    f2 = std::bind(my_strcat<const std::string,std::string>,s1,s2);
    ss = f2();
    std::cout<<ss<<endl;  
}

int _tmain(int argc, _TCHAR* argv[])
{
    test_bind();

system("pause");
    return 0;
}

/*输出结果是:

aaaBBB
aaaBBB
aaaBBB
aaaBBB
请按任意键继续. . .

*/

为了比较熟练的看懂各式各样的宏定义,现在先举出一个推导的例子。我们这里以 std::function 的
源代码为例逐步展开,追根溯源,其间各种模版和宏定义令你目不暇接,叹为观止。
0. 总体流程
总体来看,宏定义
_VARIADIC_EXPAND_0X(_CLASS_GET_FUNCTION_IMPL_CALLS, , , , )
是6个宏定义
_VARIADIC_CALL_OPT_X1,而每个_VARIADIC_CALL_OPT_X1又是3个模板类 _Get_function_impl 的定义
所以6 *3 总计是18个_Get_function_impl的定义

1. std::function 定义
std::function 申明如下
 // TEMPLATE CLASS function
template<class _Fty>
 class function
  : public _Get_function_impl<_Fty>::type
 { // wrapper for callable objects
public:
 typedef function<_Fty> _Myt;
 typedef typename _Get_function_impl<_Fty>::type _Mybase;

function() _NOEXCEPT
  { // construct empty function wrapper
  this->_Reset();
  }
  
  ......省略部分定义和实现
  
  //上面的的代码就调用了这个赋值函数
  template<class _Fx>
  _Myt& operator=(_Fx&& _Func)
  { // move function object _Func
  this->_Tidy();
  this->_Reset(_STD forward<_Fx>(_Func));
  return (*this);
  }
  
  ......省略部分定义和实现
  
private:
 template<class _Fty2>
  void operator==(const function<_Fty2>&); // not defined
 template<class _Fty2>
  void operator!=(const function<_Fty2>&); // not defined
 };

我们重点关注申明这句 template<class _Fty> class function : public _Get_function_impl<_Fty>::type,
 _Get_function_impl<_Fty>::type 何许人也,能当它的父类?
   
2.  _Get_function_impl<_Fty>
我们继续追踪,有如下定义
template<class _Tx> struct _Get_function_impl;
那不对啊,上面的定义应该不是全部的 _Get_function_impl定义。怀疑何在呢?我们看std::function 类
里面的移动赋值运算符 template<class _Fx> _Myt& operator=(_Fx&& _Func),里面的实现调用了
_Tidy(),this->_Reset(_STD forward<_Fx>(_Func));这些函数std::function 里面都没有实现啊,那只有一种可能,
是父类里面实现了这些函数,但是我们看到_Get_function_impl类并没有任何实现啊。那实现到哪里去了呢?那父
类还有那些诡异的东东呢?  下面熊出没,注意!!!

3. 追踪 _Get_function_impl
我们看到 _Get_function_impl 没有任何实现,下面还有几个名称比较类似宏定义。
#define _CLASS_GET_FUNCTION_IMPL( \
 TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, CALL_OPT, X2, X3, X4) \
template<class _Ret COMMA LIST(_CLASS_TYPE)> \
 struct _Get_function_impl<_Ret CALL_OPT (LIST(_TYPE))> \
 { /* determine type from argument list */ \
 typedef _Func_class<_Ret COMMA LIST(_TYPE)> type; \
 };

#define _CLASS_GET_FUNCTION_IMPL_CALLS( \
 TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, CALL_OPT, X2, X3, X4) \
  _VARIADIC_CALL_OPT_X1(_CLASS_GET_FUNCTION_IMPL, \
   TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, __cdecl, X2, X3, X4)

_VARIADIC_EXPAND_0X(_CLASS_GET_FUNCTION_IMPL_CALLS, , , , )

我们展开看看,里面有何端倪。

4. 展开 _VARIADIC_EXPAND_0X
我们继续追,在文件 xstddef 里面,我们发现了它的定义。xstddef 是公共的STL 实现的定义,从
文件名称可以明显的看出功能。
 // for 0-X args
#define _VARIADIC_EXPAND_0X(FUNC, X1, X2, X3, X4) \
 _VARIADIC_EXPAND_0(FUNC, X1, X2, X3, X4) \
 _VARIADIC_EXPAND_1X(FUNC, X1, X2, X3, X4)

继续展开 _VARIADIC_EXPAND_0 和 _VARIADIC_EXPAND_1X

我们把 _VARIADIC_EXPAND_1X 也全部展开
#define _VARIADIC_EXPAND_1X(FUNC, X1, X2, X3, X4) \
 _VARIADIC_EXPAND_1(FUNC, X1, X2, X3, X4) \
 _VARIADIC_EXPAND_2X(FUNC, X1, X2, X3, X4)

继续展开_VARIADIC_EXPAND_2X,注意,这里标明了最大支持5个函数参数,这个就是
 为什么 std::function 最大支持5个函数参数。
 
 #if _VARIADIC_MAX == 5
#define _VARIADIC_EXPAND_2X _VARIADIC_EXPAND_25
#define _VARIADIC_EXPAND_25(FUNC, X1, X2, X3, X4) \
 _VARIADIC_EXPAND_2(FUNC, X1, X2, X3, X4) \
 _VARIADIC_EXPAND_3(FUNC, X1, X2, X3, X4) \
 _VARIADIC_EXPAND_4(FUNC, X1, X2, X3, X4) \
 _VARIADIC_EXPAND_5(FUNC, X1, X2, X3, X4)

_VARIADIC_EXPAND_0 最终展开就是这个定义了
// call FUNC(TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, X1, X2, X3, X4)
#define _VARIADIC_EXPAND_0(FUNC, X1, X2, X3, X4) \
FUNC(_TEM_LIST0, _PAD_LIST0, _RAW_LIST0, , X1, X2, X3, X4)

_VARIADIC_EXPAND_1 最终展开就是这个定义了
#define _VARIADIC_EXPAND_1(FUNC, X1, X2, X3, X4) \
FUNC(_TEM_LIST1, _PAD_LIST1, _RAW_LIST1, _COMMA, X1, X2, X3, X4)

结果全部出来了
#define _VARIADIC_EXPAND_2(FUNC, X1, X2, X3, X4) \
FUNC(_TEM_LIST2, _PAD_LIST2, _RAW_LIST2, _COMMA, X1, X2, X3, X4)

#define _VARIADIC_EXPAND_3(FUNC, X1, X2, X3, X4) \
FUNC(_TEM_LIST3, _PAD_LIST3, _RAW_LIST3, _COMMA, X1, X2, X3, X4)

#define _VARIADIC_EXPAND_4(FUNC, X1, X2, X3, X4) \
FUNC(_TEM_LIST4, _PAD_LIST4, _RAW_LIST4, _COMMA, X1, X2, X3, X4)

#define _VARIADIC_EXPAND_5(FUNC, X1, X2, X3, X4) \
FUNC(_TEM_LIST5, _PAD_LIST5, _RAW_LIST5, _COMMA, X1, X2, X3, X4) 
 
这样,我们获取到6(索引0~5)个类似 _VARIADIC_EXPAND_ 的定义。它们最终是宏定义。
_VARIADIC_EXPAND_0(_CLASS_GET_FUNCTION_IMPL_CALLS, , , , )
_VARIADIC_EXPAND_1(_CLASS_GET_FUNCTION_IMPL_CALLS, , , , )
...
_VARIADIC_EXPAND_5(_CLASS_GET_FUNCTION_IMPL_CALLS, , , , )

我们以索引为 0 的宏定义展开为例。
_VARIADIC_EXPAND_0(_CLASS_GET_FUNCTION_IMPL_CALLS, , , , ) 展开,那对应的替换就是
// call FUNC(TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, X1, X2, X3, X4)
#define _VARIADIC_EXPAND_0(FUNC, X1, X2, X3, X4) \
FUNC(_TEM_LIST0, _PAD_LIST0, _RAW_LIST0, , X1, X2, X3, X4)

展开后就是
_VARIADIC_EXPAND_0(_CLASS_GET_FUNCTION_IMPL_CALLS, , , , )
就是
_CLASS_GET_FUNCTION_IMPL_CALLS(_TEM_LIST0, _PAD_LIST0, _RAW_LIST0, , X1, X2, X3, X4)
但是这样展开后,我们还是没有看到一个任何类的定义和实现,那继续...

5. 宏 _CLASS_GET_FUNCTION_IMPL_CALLS
#define _CLASS_GET_FUNCTION_IMPL_CALLS( \
 TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, CALL_OPT, X2, X3, X4) \
  _VARIADIC_CALL_OPT_X1(_CLASS_GET_FUNCTION_IMPL, \
   TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, __cdecl, X2, X3, X4)
通过定义,我们展开 _CLASS_GET_FUNCTION_IMPL_CALLS 宏。还是以索引 0的为例,能得到下面
的定义:
_VARIADIC_CALL_OPT_X1(_CLASS_GET_FUNCTION_IMPL, _TEM_LIST0, _PAD_LIST0, _RAW_LIST0,,__cdecl,X2, X3, X4)

6. 宏_VARIADIC_CALL_OPT_X1
我们来看看这个嵌套在里面的宏.
#define _VARIADIC_CALL_OPT_X1(FUNC, X1, X2, X3, X4, \
 CALL_OPT, X6, X7, X8) \
  FUNC(X1, X2, X3, X4, CALL_OPT, X6, X7, X8) \
  FUNC(X1, X2, X3, X4, __stdcall, X6, X7, X8) \
  FUNC(X1, X2, X3, X4, __fastcall, X6, X7, X8)

那实际上展开就是3个如下的宏定义
_CLASS_GET_FUNCTION_IMPL(_TEM_LIST0, _PAD_LIST0, _RAW_LIST0, , __cdecl,X2, X3, X4)
_CLASS_GET_FUNCTION_IMPL(_TEM_LIST0, _PAD_LIST0, _RAW_LIST0, , __stdcall,X2, X3, X4)
_CLASS_GET_FUNCTION_IMPL(_TEM_LIST0, _PAD_LIST0, _RAW_LIST0, , __fastcall,X2, X3, X4)

7. 宏 _CLASS_GET_FUNCTION_IMPL
我们来看 _CLASS_GET_FUNCTION_IMPL 的定义
#define _CLASS_GET_FUNCTION_IMPL( \
 TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, CALL_OPT, X2, X3, X4) \
template<class _Ret COMMA LIST(_CLASS_TYPE)> \
 struct _Get_function_impl<_Ret CALL_OPT (LIST(_TYPE))> \
 { /* determine type from argument list */ \
 typedef _Func_class<_Ret COMMA LIST(_TYPE)> type; \
 
 };
 
8. 获取原型
结合上面对宏_CLASS_GET_FUNCTION_IMPL的使用,我们能大致获取到下面的定义,我们以
_CLASS_GET_FUNCTION_IMPL(_TEM_LIST0, _PAD_LIST0, _RAW_LIST0, , __cdecl,X2, X3, X4)
为例展:
template<class _Ret  _RAW_LIST0(_CLASS_TYPE)> \
 struct _Get_function_impl<_Ret __cdecl (_RAW_LIST0(_TYPE))> \
 { /* determine type from argument list */ \
 typedef _Func_class<_Ret _RAW_LIST0(_TYPE)> type; \
 };
 
  #define _RAW_LIST0(MAP)
  #define _VAR_VAL(NUM) _V ## NUM
#define _VAR_TYPE(NUM) _V ## NUM ## _t
#define _CLASS_TYPE(NUM) class _VAR_TYPE(NUM)

template<class _Ret> struct _Get_function_impl<_Ret __cdecl()>
{
 typedef _Func_class<_Ret)> type;
};


_CLASS_GET_FUNCTION_IMPL(_TEM_LIST0, _PAD_LIST0, _RAW_LIST0, , __stdcall,X2, X3, X4)
_CLASS_GET_FUNCTION_IMPL(_TEM_LIST0, _PAD_LIST0, _RAW_LIST0, , __fastcall,X2, X3, X4)
对应就是

template<class _Ret> struct _Get_function_impl<_Ret __stdcall()>
{
 typedef _Func_class<_Ret)> type;
};

template<class _Ret> struct _Get_function_impl<_Ret __fastcall()>
{
 typedef _Func_class<_Ret)> type;
};

9. 我们以 _VARIADIC_EXPAND_2 为例来再推导一次

_VARIADIC_EXPAND_0X(_CLASS_GET_FUNCTION_IMPL_CALLS, , , , )
开始,得到
#define _VARIADIC_EXPAND_2(FUNC, X1, X2, X3, X4) \
FUNC(_TEM_LIST2, _PAD_LIST2, _RAW_LIST2, _COMMA, X1, X2, X3, X4)
可以得到
_CLASS_GET_FUNCTION_IMPL_CALLS(_TEM_LIST2, _PAD_LIST2, _RAW_LIST2, _COMMA, X1, X2, X3, X4)
进而得到
_VARIADIC_CALL_OPT_X1(_CLASS_GET_FUNCTION_IMPL, _TEM_LIST2, _PAD_LIST2, _RAW_LIST2, _COMMA,__cdecl, X2, X3, X4)
继续展开,得到
_CLASS_GET_FUNCTION_IMPL(_TEM_LIST2,_PAD_LIST2,_RAW_LIST2,_COMMA,__cdecl,X2, X3, X4)
_CLASS_GET_FUNCTION_IMPL(_TEM_LIST2,_PAD_LIST2,_RAW_LIST2,_COMMA,__stdcall,X2, X3, X4)
_CLASS_GET_FUNCTION_IMPL(_TEM_LIST2,_PAD_LIST2,_RAW_LIST2,_COMMA,__fastcall,X2, X3, X4)
继续展开,得到(先用__cdecl为例)
#define _CLASS_GET_FUNCTION_IMPL( \
 TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, CALL_OPT, X2, X3, X4) \
template<class _Ret _COMMA _RAW_LIST2(_CLASS_TYPE)> \
 struct _Get_function_impl<_Ret __cdecl (_RAW_LIST2(_TYPE))> \
 { /* determine type from argument list */ \
 typedef _Func_class<_Ret _COMMA _RAW_LIST2(_TYPE)> type; \
 };

#define _RAW_LIST2(MAP) MAP(0) _COMMA MAP(1)
#define _RAW_LIST0(MAP)
#define _RAW_LIST2(MAP) MAP(0) _COMMA MAP(1)
#define _VAR_VAL(NUM) _V ## NUM
#define _VAR_TYPE(NUM) _V ## NUM ## _t
#define _CLASS_TYPE(NUM) class _VAR_TYPE(NUM)
#define _TYPE(NUM)  _VAR_TYPE(NUM)

全部继续展开,
template<class _Ret , class _V0_t class _V1_t>  
struct _Get_function_impl<_Ret __cdecl (_V0_t,_V1_t))>
{
 typedef _Func_class<_Ret, _V0_t,_V1_t> type;
};

template<class _Ret , class _V0_t class _V1_t>  
struct _Get_function_impl<_Ret __cdecl (_V0_t,_V1_t))>
{
 typedef _Func_class<_Ret, _V0_t,_V1_t> type;
};

template<class _Ret , class _V0_t class _V1_t>  
struct _Get_function_impl<_Ret __stdcall (_V0_t,_V1_t))>
{
 typedef _Func_class<_Ret, _V0_t,_V1_t> type;
};

10. 我们发现,
_VARIADIC_EXPAND_0 对应的是类似这样的定义
template<class _Ret> struct _Get_function_impl<_Ret __stdcall()>
{
 typedef _Func_class<_Ret)> type;
};

_VARIADIC_EXPAND_1 对应的是类似这样的定义
template<class _Ret,_V0_t> struct _Get_function_impl<_Ret __stdcall(_V0_t)>
{
 typedef _Func_class<_Ret,_V0_t)> type;
};

_VARIADIC_EXPAND_2 对应的是类似这样的定义
template<class _Ret,_V0_t,_V1_t> struct _Get_function_impl<_Ret __stdcall(_V0_t,_V1_t)>
{
 typedef _Func_class<_Ret,_V0_t,_V1_t)> type;
};

_VARIADIC_EXPAND_5 对应的是类似这样的定义,5表示有5个参数
template<class _Ret,_V0_t,_V1_t,_V2_t,_V3_t,_V4_t> struct _Get_function_impl<_Ret __stdcall(_V0_t,_V1_t,_V2_t,_V3_t,_V4_t)>
{
 typedef _Func_class<_Ret,_V0_t,_V1_t,_V2_t,_V3_t,_V4_t)> type;
};

自此,全部推导结束,也就能理解类是构造的了。

最新文章

  1. 显示快照监控:/SDF/MON
  2. RSA Study
  3. spring ioc原理
  4. Redis Sentinel机制与用法(一)
  5. XPath 教程
  6. C++中的基类与派生类
  7. automake使用
  8. Gvim使用心得--设置篇[转]
  9. EBS收单方/收货方
  10. 阅读安卓在线(Android)系统源代码
  11. (三)—Linux文件传输与mysql数据库安装
  12. 关于jquery ajax跨域请求获取response headers问题
  13. 系列博文-Three.js入门指南(张雯莉)-网格 setInterval方法 requestAnimationFrame方法 使用stat.js记录FPS
  14. Lunix服务器上项目迁移命令
  15. node踩坑之This is probably not a problem with npm. There is likely additional logging output above.错误
  16. IEnumerable和IEnumerator接口
  17. Ford VCM II Ford VCM2 Diagnostic Tool with Ford IDS v108 Installed On Laptop Ready to Use
  18. Confluence 6 指派空间权限概念
  19. 学会清理.rncache 文件、清理已经安装的三方文件,三方引入文件
  20. smyfony2-curd-数据库创建

热门文章

  1. SQL数据转移
  2. Family Tree
  3. Unique Paths 解答
  4. Django的安装配置和开发
  5. jQuery -&amp;gt; end方法的使用方法
  6. 深入浅出:重温JAVA中接口与抽象的区别
  7. SqlServer判断数据库、表、存储过程、函数是否存在
  8. HTML中的figure与figcaption标签
  9. LINQ 操作符
  10. &lt;转&gt;Python的内存泄漏及gc模块的使用分析