有了点模板元编程的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 base
typedef _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 false
typedef _Ty2 type;
}; template<class _Ty1,
class _Ty2>
struct _If<true, _Ty1, _Ty2>
{ // type is _Ty1 for assumed true
typedef _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 iterators
typedef _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 head private:
_List_node& operator=(const _List_node&);
}; template<class _Value_type>
struct _List_node<_Value_type, void *>
{ // list node
typedef _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 head private:
_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 iterators
typedef _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&(常饮用)

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

【STL源码学习】std::list类的类型别名分析的更多相关文章

  1. stl源码学习(版本2.91)--list

    stl源码学习(版本2.91)--list 一,阅读list()构造函数的收获 1,默认构造函数的作用和被调用的时机 struct no{ no(int i){} //no(){ // std::co ...

  2. 【STL源码学习】STL算法学习之二

    第一章:前言 学习笔记,记录学习STL算法的一些个人所得,在以后想用的时候可以快速拾起. 第二章:明细 copy 函数原型: template <class InputIterator, cla ...

  3. 【STL源码学习】细品vector

    第一节:vector简介 vector是一种典型的类模板,使用的时候必须进行实例化. vector的数据存储在数组上,支持随机访问迭代器,支持下标操作[]和at操作,支持手动扩容和自动容量增长. ve ...

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

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

  5. STL源码学习----lower_bound和upper_bound算法

    转自:http://www.cnblogs.com/cobbliu/archive/2012/05/21/2512249.html 先贴一下自己的二分代码: #include <cstdio&g ...

  6. STL源码学习----lower_bound和upper_bound算法[转]

    STL中的每个算法都非常精妙,接下来的几天我想集中学习一下STL中的算法. ForwardIter lower_bound(ForwardIter first, ForwardIter last,co ...

  7. 【STL源码学习】STL算法学习之三

    第一章:前言 数量不多,用到的时候会很爽. 第二章:明细 STL算法中的又一个分类:分割:将已有元素按照既定规则分割成两部分.  is_partitioned 函数原型: template <c ...

  8. 【STL源码学习】STL算法学习之一

    第一章:引子 STL包含的算法头文件有三个:<algorithm><numeric><functional>,其中最大最常用的是<algorithm>, ...

  9. [Android FrameWork 6.0源码学习] Window窗口类分析

    了解这一章节,需要先了解LayoutInflater这个工具类,我以前分析过:http://www.cnblogs.com/kezhuang/p/6978783.html Window是Activit ...

随机推荐

  1. Python -- 使用pickle 和 CPickle对数据对象进行归档和解析

    经常遇到在Python程序运行中得到了一些字符串.列表.字典.对象等数据,想要长久的保存下来,方便以后使用,而不是简单的放入内存中关机断电就丢失数据. 这个时候Pickle模块就派上用场了,它可以将对 ...

  2. ie下的bug之button

    场景描述: 现在页面设计是都喜欢自定义按钮样式,某日接收到页面发现在ie下有bug,上代码: <div> <button><span><a href=&quo ...

  3. CMDB Autoclient思路分析

    1.start.py里的script.run():执行run函数--> 2.script.py run方法--> 3.判断模式MODE(Agent/SSHSALT)-->4.执行cl ...

  4. CMDB配置资源管理数据库(理解)

    CMDB是运维自动化的基础,它为日志系统,发布系统,监控系统等运维系统(ELK,zabbix,open-falcon)提供接口函数, 第一种方式:Agent方法实现,agent不能直接访问数据库,因为 ...

  5. Java基础学习-Collection体系结构和迭代测试

    package Collection; import java.util.ArrayList; import java.util.Collection; import java.util.Iterat ...

  6. SQL 动态PIVOT查询

    DECLARE @sql_str VARCHAR(8000)DECLARE @sql_col VARCHAR(8000) SELECT @sql_col = ISNULL(@sql_col + ',' ...

  7. 2.JSR简介 - JavaEE基础系列

    JSR, Java Specification Request, Java规范请求; 也有的地方翻译为Java规范提案. 在前面的文章 1. Java EE简介 - JavaEE基础系列中, 简要介绍 ...

  8. [知识图谱] 环境配置:Java8 + Maven3 + HBase + Titan

    1.Java Java8安装配置 2.Maven Linux下的Maven安装与配置 3.Hbase 官方安装教程:http://s3.thinkaurelius.com/docs/titan/1.0 ...

  9. python学习之多线程(二)

    使用multiprocessing 使用multiprocessing.dummy 单使用multiprocessing模块的指的是多进程,使用multiprocessing.dummy则表示使用的是 ...

  10. Linux服务器运行环境搭建(二)——Redis数据库安装

    官网地址:http://redis.io/ 官网下载地址:http://redis.io/download 1. 下载Redis源码(tar.gz),并上传到Linux 2. 解压缩包:tar zxv ...