热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

有了点模板元编程的traits基础,看STL源码清晰多了,以前看源码的时候总被各种各样的typedef给折腾得看不下去,将<list>头文件的类继承结构简化如下#include<x

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

头文件的类继承结构简化如下

#include 
#include

#define _STD_BEGIN namespace std {
#define _STD_END }

_STD_BEGIN

// 第一个模板参数
template
class _List_val : public _Container_base { };

// 第二个模板参数
template
struct _List_base_types { };

template
class _List_alloc
: public _List_val { };

template // 这里默认_Alloc不为空类型
class _List_buy // !is_empty<_Alloc>::value暂不讨论
: public _List_alloc> { };

template >
class list : public _List_buy<_Ty, _Alloc> { };

_STD_END

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

_Ty被替换成int,_Alloc默认被替换成allocator,上一层基类_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

templateclass _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_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,
_List_iter_typestypename _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来完成类型计算。

templateclass _Ty1,
class _Ty2>
struct _If
{// type is _Ty2 for assumed false
typedef _Ty2 type;
};

templateclass _Ty2>
struct _If
{// 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
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 *>

templateclass _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
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
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&(常饮用)

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


推荐阅读
author-avatar
odile微笑头
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有