STL源码剖析——iterators与trait编程#4 iterator源码

  在前两节介绍了迭代器的五个相应类型,并讲述如何利用traits机制提取迭代器的类型,但始终是把iteartor_traits类分割开来讨论,这影响我们的理解,本节将给出iteator的部分源码,里面涵盖了整个iteartor_traits泛化版本、偏特化版本以及一些算法的完整代码。重新把先前讲的知识捋顺一下。

  1 //节选自SGI STL<stl_iterator.h>
  2
  3 //五种迭代器类型,继承表示,越底层的基类越低级,越上层的子类越高级
  4 struct input_iterator_tag {};
  5 struct output_iterator_tag {};
  6 struct forward_iterator_tag : public input_iterator_tag {};
  7 struct bidirectional_iterator_tag : public forward_iterator_tag {};
  8 struct random_access_iterator_tag : public bidirectional_iterator_tag {};
  9
 10 //要使自己设计的迭代器符合STL的规范,最好继承自下面的std::iterator
 11 template <class Category, class T, class Distance = ptrdiff_t,
 12     class Pointer = T*, class Reference = T&>
 13     struct iterator {
 14     typedef Category  iterator_category;
 15     typedef T         value_type;
 16     typedef Distance  difference_type;
 17     typedef Pointer   pointer;
 18     typedef Reference reference;
 19 };
 20
 21 //提取迭代器五个相应类型的榨汁机iterator_traits,可以看到迭代器其特性均来自迭代器本身,说明设计迭代器时候就应该考虑提供这五个相应类型。所以为了防止自己设计时有所遗漏,继承std::iterator是上策
 22 template <class Iterator>
 23 struct iterator_traits {
 24     typedef typename Iterator::iterator_category iterator_category;
 25     typedef typename Iterator::value_type        value_type;
 26     typedef typename Iterator::difference_type   difference_type;
 27     typedef typename Iterator::pointer           pointer;
 28     typedef typename Iterator::reference         reference;
 29 };
 30 //针对原生指针而设计的traits偏特化版本
 31 template <class T>
 32 struct iterator_traits<T*> {
 33     typedef random_access_iterator_tag iterator_category;
 34     typedef T                          value_type;
 35     typedef ptrdiff_t                  difference_type;
 36     typedef T*                         pointer;
 37     typedef T&                         reference;
 38 };
 39 //针对原生pointer-to-const而设计的traits偏特化版本
 40 template <class T>
 41 struct iterator_traits<const T*> {
 42     typedef random_access_iterator_tag iterator_category;
 43     typedef T                          value_type;
 44     typedef ptrdiff_t                  difference_type;
 45     typedef const T*                   pointer;
 46     typedef const T&                   reference;
 47 };
 48 //全局函数,这个函数可以很方便地决定某个迭代器的类型
 49 template <class Iterator>
 50 inline typename iterator_traits<Iterator>::iterator_category
 51 iterator_category(const Iterator&) {
 52     typedef typename iterator_traits<Iterator>::iterator_category category;    //使用traits机制提取其iterator category
 53     return category();
 54 }
 55 //全局函数,这个函数可以很方便地决定某个迭代器的distance type
 56 template <class Iterator>
 57 inline typename iterator_traits<Iterator>::difference_type*
 58 distance_type(const Iterator&) {
 59     return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
 60 }
 61 //全局函数,这个函数可以很方便地决定某个迭代器的value type
 62 template <class Iterator>
 63 inline typename iterator_traits<Iterator>::value_type*
 64 value_type(const Iterator&) {
 65     return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
 66 }
 67
 68 //整组distance函数,该函数有计算两迭代器距离的功能
 69 template <class InputIterator, class Distance>
 70 inline void __distance(InputIterator first, InputIterator last, Distance& n,
 71     input_iterator_tag) {        //如果是非随机迭代器,只能每次循环都要判断是否到达last迭代器
 72     while (first != last) { ++first; ++n; }
 73 }
 74
 75 template <class RandomAccessIterator, class Distance>
 76 inline void __distance(RandomAccessIterator first, RandomAccessIterator last,
 77     Distance& n, random_access_iterator_tag) {    //随机迭代器,不用做两迭代器是否相同的比较,由于提供了operator-(),直接减法处理,速度比前者快
 78     n += last - first;
 79 }
 80
 81 template <class InputIterator, class Distance>
 82 inline void distance(InputIterator first, InputIterator last, Distance& n) {
 83     __distance(first, last, n, iterator_category(first));    //使用上面提到的iterator_category()全局函数决定哪个迭代器类型
 84 }
 85
 86 //以下是整组advance函数,该函数具有从某迭代器出发跳跃到指定距离位置的功能
 87 template <class InputIterator, class Distance>
 88 inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
 89     while (n--) ++i;    //使用非随机单向迭代器,只能逐次前进至指定位置
 90 }
 91
 92 template <class BidirectionalIterator, class Distance>
 93 inline void __advance(BidirectionalIterator& i, Distance n,
 94     bidirectional_iterator_tag) {    //使用双向迭代器,可能往前或往后移动,但也是只能逐次移动至指定位置
 95     if (n >= 0)
 96         while (n--) ++i;
 97     else
 98         while (n++) --i;
 99 }
100
101 template <class RandomAccessIterator, class Distance>
102 inline void __advance(RandomAccessIterator& i, Distance n,
103     random_access_iterator_tag) {    //随机迭代器,真正的跳跃
104     i += n;
105 }
106
107 template <class InputIterator, class Distance>
108 inline void advance(InputIterator& i, Distance n) {
109     __advance(i, n, iterator_category(i));    //使用上面提到的iterator_category()全局函数决定哪个迭代器类型
110 }

原文地址:https://www.cnblogs.com/MisakiJH/p/11686092.html

时间: 2024-11-09 14:39:14

STL源码剖析——iterators与trait编程#4 iterator源码的相关文章

STL源码剖析——iterators与trait编程#2 Traits编程技法

在算法中运用迭代器时,很可能用到其相应类型.什么是相应类型?迭代器所指对象的类型便是其中一个.我曾有一个错误的理解,那就是认为相应类型就是迭代器所指对象的类型,其实不然,相应类型是一个大的类别,迭代器所指对象的类型只是里面的其中一个.后面会讨论到相应类型的另外几种. 假设算法需要声明一个变量,以“迭代器所指对象的类型”为类型,该怎么做?或许我们可能会想到RTTI性质中的typeid(),但获得的只是类型名称,并不能拿来声明变量. 其中一个解决方法是:利用模版函数中的参数推导(argument d

STL源码剖析——iterators与trait编程#3 iterator_category

最后一个迭代器的相应类型就是iterator_category,就是迭代器本身的类型,根据移动特性与实行的操作,迭代器被分为了五类: Input Iterator:这种迭代器所指的对象,不允许外界改变.只读(read only). Output Iterator:唯写(write only) Forward Iterator:允许写入型算法在此种迭代器所形成的区间上进行读写操作,具有Input迭代器的全部功能和Output迭代器的大部分功能.支持++运算符. Bidirectional Iter

STL源码剖析——iterators与trait编程#1 尝试设计一个迭代器

STL的中心思想在于:将数据容器与算法分开,独立设计,再用一帖粘着剂将它们撮合在一起.而扮演粘着剂这个角色的就是迭代器.容器和算法泛型化,从技术角度来看并不困难,C++的模板类和模板函数可分别达成目标,但如何设计出两者之间良好的粘着剂,才是大难题. 我们可以来尝试一下自己设计一个迭代器,看途中会遇到一些什么样的难题,同时看看SGI STL是怎么解决它们的.不过在此之前,我们可以先使用一下迭代器,看看其有什么样的功能,以find()函数为例: 1 //来自SGI <stl_algo.h> 2 t

STL源码剖析——Iterators与Traits编程#5 __type_traits

上节给出了iterator_traits以及用到traits机制的部分函数的完整代码,可以看到traits机制能够提取迭代器的特性从而调用不同的函数,实现效率的最大化.显然这么好的机制不应该仅局限于在STL里面使用,在前某一节中我们也有说到,traits机制能够萃取类的特性,而这个类分为两个类别,一是迭代器类,二普通类,迭代器类我们已经有所了解了,那么本节就来学习负责萃取普通类型特性的__type_traits吧. 于普通类型而言,我们所关注的特性是指:这个类型是否具备non-trivial d

STL源码剖析—迭代器与traits编程方法

STL的中心思想就是将算法和容器分开,彼此独立设计,最后再以粘合在一起,算法和容器的泛型化,并不是很难,C++的class templates和function templates可以达成目标,但是粘合在一起就是迭代器的事情. 这么一说迭代器就是为了粘合算法和容器的,如果单独设计迭代器,那么这个迭代器就必须知道某个特定容器的内部数据,会暴露太多的信息,这样就规定每一种STL容器都提供有专属迭代器. 迭代器所指对象的型别,称为该迭代器的value_type.所谓value_type,是指迭代器所指

《Apache Spark源码剖析》

Spark Contributor,Databricks工程师连城,华为大数据平台开发部部长陈亮,网易杭州研究院副院长汪源,TalkingData首席数据科学家张夏天联袂力荐1.本书全面.系统地介绍了Spark源码,深入浅出,细致入微2.提供给读者一系列分析源码的实用技巧,并给出一个合理的阅读顺序3.始终抓住资源分配.消息传递.容错处理等基本问题,抽丝拨茧4.一步步寻找答案,所有问题迎刃而解,使读者知其然更知其所以然 内容简介 书籍计算机书籍 <Apache Spark源码剖析>以Spark

Redis源码剖析和注释(八)--- 对象系统(redisObject)

Redis 对象系统 1. 介绍 redis中基于双端链表.简单动态字符串(sds).字典.跳跃表.整数集合.压缩列表.快速列表等等数据结构实现了一个对象系统,并且实现了5种不同的对象,每种对象都使用了至少一种前面的数据结构,优化对象在不同场合下的使用效率. 双端链表源码剖析和注释 简单动态字符串(SDS)源码剖析和注释 字典结构源码剖析和注释 跳跃表源码剖析和注释 整数集合源码剖析和注释 压缩列表源码剖析和注释 快速列表源码剖析和注释 2. 对象的系统的实现 redis 3.2版本.所有注释在

ConcurrentHashMap基于JDK1.8源码剖析

前言 声明,本文用的是jdk1.8 前面章节回顾: Collection总览 List集合就这么简单[源码剖析] Map集合.散列表.红黑树介绍 HashMap就是这么简单[源码剖析] LinkedHashMap就这么简单[源码剖析] TreeMap就这么简单[源码剖析] 本篇主要讲解ConCurrentHashMap~ 看这篇文章之前最好是有点数据结构的基础: Java实现单向链表 栈和队列就是这么简单 二叉树就这么简单 当然了,如果讲得有错的地方还请大家多多包涵并不吝在评论去指正- 一.Co

stl源码剖析学习笔记(二)traits编程技法简明例程

解释说明 traits侯捷老师的翻译是萃取.其目的就是在编译期进行模板调用的类型识别,从而做一些事情. 最突出的例子,我觉得不是<STL源码剖析>中"迭代器概念与traits编程技法"这一章的说明,而是stl算法中copy的实现.代码在stl源码的stl_algobase.h中. copy的最终实现,大致分为两类,一类是直接整块内存的memmove操作,另一类是一个个对象赋值.其中涉及has_trivial_assignment_operator的类型推断. 如果has_t