有了点模板元编程的traits基础,看STL源码清晰多了,以前看源码的时候总被各种各样的typedef给折腾得看不下去,

将<list>头文件的类继承结构简化如下

#include <xmemory>
#include <stdexcept>#define _STD_BEGIN namespace std {
#define _STD_END }_STD_BEGIN// 第一个模板参数
template <class _Val_types>
class _List_val : public _Container_base { };// 第二个模板参数
template <class _Ty, class _Alloc0>
struct _List_base_types { };template <bool _Al_has_storage, class _Alloc_types>
class _List_alloc: public _List_val<typename _Alloc_types::_Val_types> { };template <class _Ty, class _Alloc>  // 这里默认_Alloc不为空类型
class _List_buy     // !is_empty<_Alloc>::value暂不讨论: public _List_alloc<true, _List_base_types<_Ty, _Alloc>> { };template <class _Ty, class _Alloc = allocator<_Ty> >
class list : public _List_buy<_Ty, _Alloc> { };_STD_END

举个例子,看看list<int>这个实例化会产生什么效果,从下往上看。

_Ty被替换成int,_Alloc默认被替换成allocator<int>,上一层基类_List_buy的两个模板参数也是_Ty和_Alloc

再上一层基类_List_alloc有2个模板参数,第一个是bool值,编译期判断是否为空类型(empty class),第二个则是由_Ty和_Alloc两个模板参数实例化的_List_base_types类,该类没有基类型,这个类如同名字所说,list的基本类型。

_List_alloc的基类_List_val也是由_List_base_types作为模板参数实例化,_List_val的基类Container_base0仅仅包含两个函数体内为空的函数。

结论:list<>进行实例化后,模板参数_Ty是通过_List_base_types来定义list各类中的类型别名。

现在来看看_List_base_types内部的typedef

template<class _Ty,class _Alloc0>struct _List_base_types{ // types needed for a container basetypedef _Alloc0 _Alloc;typedef _List_base_types<_Ty, _Alloc> _Myt;typedef _Wrap_alloc<_Alloc> _Alty0;typedef typename _Alty0::template rebind<_Ty>::other _Alty;typedef typename _Get_voidptr<_Alty, typename _Alty::pointer>::type_Voidptr;typedef _List_node<typename _Alty::value_type,_Voidptr> _Node;typedef typename _Alty::template rebind<_Node>::other _Alnod_type;typedef typename _Alnod_type::pointer _Nodeptr;typedef _Nodeptr& _Nodepref;typedef typename _If<_Is_simple_alloc<_Alty>::value,_List_simple_types<typename _Alty::value_type>,_List_iter_types<typename _Alty::value_type,typename _Alty::size_type,typename _Alty::difference_type,typename _Alty::pointer,typename _Alty::const_pointer,typename _Alty::reference,typename _Alty::const_reference,_Nodeptr> >::type_Val_types;};

_Myt为实例化后的该类模板的别名。

先看看最后的关键的_Val_types,变量类型,通过元函数(Meta Function)_If来完成类型计算。

template<bool,class _Ty1,class _Ty2>struct _If{  // type is _Ty2 for assumed falsetypedef _Ty2 type;};template<class _Ty1,class _Ty2>struct _If<true, _Ty1, _Ty2>{   // type is _Ty1 for assumed truetypedef _Ty1 type;};

通过模板特化来完成编译期的判断,三个模板参数,第一个为bool,如果第一个参数为true,那么类型type是_Ty1,否则类型type是_Ty2。

_Val_types第一个参数<_Is_simple_alloc<_Alty>::value,判断_Alty是否为“简单的内存分配器”,如果不是,则意味着你专门定制了特殊的内存分配器(类),并将这个类的类型别名(size_type、pointer等等)传递给_Val_types。

如果是,就直接用_List_simple_types,也就是list的简单类型。

template<class _Ty>struct _List_simple_types: public _Simple_types<_Ty>{   // wraps types needed by iteratorstypedef _List_node<_Ty, void *> _Node;typedef _Node *_Nodeptr;};

到这里就可以发现,链表类必须用到的结点类就在这里:_List_node<_Ty, void *>

template<class _Value_type,class _Voidptr>struct _List_node{    // list node_Voidptr _Next; // successor node, or first element if head_Voidptr _Prev;  // predecessor node, or last element if head_Value_type _Myval; // the stored value, unused if headprivate:_List_node& operator=(const _List_node&);};template<class _Value_type>struct _List_node<_Value_type, void *>{   // list nodetypedef _List_node<_Value_type, void *> *_Nodeptr;_Nodeptr _Next; // successor node, or first element if head_Nodeptr _Prev;  // predecessor node, or last element if head_Value_type _Myval; // the stored value, unused if headprivate:_List_node& operator=(const _List_node&);};

结点类包含前向指针和后向指针,双向链表,并且把赋值运算符的重载置为private,禁止了结点间进行赋值。

因为进行赋值如果是简单的引用传递,没有意义,如果新建了个一模一样的结点,链表就不再是链表,而形成了闭合的图结构。

至于它的基类_Simple_types<_Ty>则是一些基本类型的集合

        // TEMPLATE CLASS _Simple_types
template<class _Value_type>struct _Simple_types{  // wraps types needed by iteratorstypedef _Value_type value_type;typedef size_t size_type;typedef ptrdiff_t difference_type;typedef value_type *pointer;typedef const value_type *const_pointer;typedef value_type& reference;typedef const value_type& const_reference;};

比如_Ty为int的话,_Simple_types里面的类型别名就是

int(值类型)、size_t(尺寸类型)、ptrdiff_t(差数类型)、int*(指针)、const int*(常指针)、int&(引用)、const int&(常饮用)

用了一些通用的接口来实现类型的统一。

转载于:https://www.cnblogs.com/Harley-Quinn/p/5645173.html

【STL源码学习】std::list类的类型别名分析相关推荐

  1. STL源码学习之空间配置

    STL的空间配置器主要用于内存的分配.填充.释放等操作,在学习它之前,需要深入一点理解new和delete.由于new和delete分两段操作:内存配置和对象构建(析构),本文亦将按此进行分类,其中第 ...

  2. JDK11源码学习05 | HashMap类

    JDK11源码学习05 | HashMap类 JDK11源码学习01 | Map接口 JDK11源码学习02 | AbstractMap抽象类 JDK11源码学习03 | Serializable接口 ...

  3. sgi stl源码学习

    c++ stl 源码分析 list类之merge函数 template <class _Tp, class _Alloc> void list<_Tp, _Alloc>::me ...

  4. C++ Standard Stl -- SGI STL源码学习笔记(07) stl_vector 与 一些问题的细化 3 resize函数剖析...

    前面在介绍push_back函数的时候有说到placement new的用法.前面说的很简单.这几天处理一些其他的事情,直到昨天下午 才有时间看源码,顺便安静的看一下书. 其中我又看到了挂关于plac ...

  5. STL源码学习(2)-迭代器概念与traits编程技法

    文章首发于:My Blog 欢迎大佬们前来逛逛 文章目录 1. 迭代器设计思维 1.2 迭代器的相应型别 1.3 Traits编程技巧 1.3.1 value_type 1.3.2 deference ...

  6. Mono源码学习笔记:Console类(四)

    NullStream 类 (internal class) 以下就是 mcs/class/corlib/System.IO/NullStream.cs: 01: namespace System.IO ...

  7. JAVA源码学习(一)——String类

    一.String类的不可变性 源码: public final class String//final修饰类,不可继承 private final char value[];//String类实际返回 ...

  8. STL源码学习(一)迭代器概念与traits编程技法

    STL的中心思想在于:将数据容器和算法分开,彼此独立设计,最后再以一贴胶着剂将它们撮合在一起.这种胶着剂便是迭代器,迭代器设计的目的在于可以方便的获取(遍历)容器中的数据同时又不暴露容器的内部实现. ...

  9. STL源码学习----集合相关算法

    STL一共提供了四种与集合相关的算法,分别是并集(union), 交集(intersection),差集(difference),对称差集(symmetric difference). 这四种集合算法 ...

最新文章

  1. CoreData的简单使用
  2. DSP的EMIF接口通信FPGA
  3. python socketpool:通用连接池
  4. linux安装后硬盘变小,Linux硬盘安装步骤
  5. java restful项目打包_听说你在接私活? 一个助你效率翻倍的项目工具!!
  6. LoadRunner 12.02 安装教程及中文语言包安装
  7. 让python脚本像普通程序一样运行
  8. 匈牙利算法-指派问题、二分图问题等
  9. STM8学习笔记---新建IAR工程文件
  10. IntelliJ IDEA 2018.2.2及以下版本破解方法
  11. Python中pip版本升级error:You are using pip version 7.1.2, however version 8.1.1 is available.
  12. 如何远程linux服务器桌面,LINUX操作系统如何远程登录桌面
  13. H - Going in Cycle!! (UVA - 11090)
  14. bodymovin输出Json动画为黑白的解决方案
  15. 当北极光遇上阿里旅行:我是旅游IP梦工场,哪里需要那里往
  16. encode()和decode()编码与解码的解析、常用编码与为何要encode和decode
  17. 考拉验数(自动化验数)设计方案和实现
  18. 动漫设计系统(基于ASP.NET的动态网站)
  19. 张朝阳喊话俞敏洪:为什么还不退休?
  20. 网络笔记(29) 容器网络:来去自由的日子,不买公寓去合租

热门文章

  1. 漫步数学分析十二——嵌套
  2. 平行空间怎么设置32位_每周推荐 | 空间占用减小32%,具有高级功能的16位逻辑封装...
  3. CS224n —— lecture2的重难点讲解
  4. python中Scrapy的安装详细过程
  5. Ubuntu16.04 sudo apt-get install lib***-dev安装失败,无法锁定文件,sudo apt-get update 更新失败也无法解决
  6. 1601 - The Morning after Halloween
  7. 80C51汇编语言有哪几条常用伪指令,单片微机原理与接口技术答案(宋跃版)
  8. python function terminated un_绕过 RestrictedUnpickler
  9. 深度学习算法_深度学习算法
  10. 同步方法中的锁对象_互斥锁与读写锁:如何使用锁完成Go程同步?