在前两节介绍了迭代器的五个相应类型,并讲述如何利用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*>();
  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*>();
  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 >= )
  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. }

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

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

    在算法中运用迭代器时,很可能用到其相应类型.什么是相应类型?迭代器所指对象的类型便是其中一个.我曾有一个错误的理解,那就是认为相应类型就是迭代器所指对象的类型,其实不然,相应类型是一个大的类别,迭代器 ...

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

    最后一个迭代器的相应类型就是iterator_category,就是迭代器本身的类型,根据移动特性与实行的操作,迭代器被分为了五类: Input Iterator:这种迭代器所指的对象,不允许外界改变 ...

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

    STL的中心思想在于:将数据容器与算法分开,独立设计,再用一帖粘着剂将它们撮合在一起.而扮演粘着剂这个角色的就是迭代器.容器和算法泛型化,从技术角度来看并不困难,C++的模板类和模板函数可分别达成目标 ...

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

    上节给出了iterator_traits以及用到traits机制的部分函数的完整代码,可以看到traits机制能够提取迭代器的特性从而调用不同的函数,实现效率的最大化.显然这么好的机制不应该仅局限于在 ...

  5. 《python解释器源码剖析》第8章--python的字节码与pyc文件

    8.0 序 我们日常会写各种各样的python脚本,在运行的时候只需要输入python xxx.py程序就执行了.那么问题就来了,一个py文件是如何被python变成一系列的机器指令并执行的呢? 8. ...

  6. Apache Spark源码剖析

    Apache Spark源码剖析(全面系统介绍Spark源码,提供分析源码的实用技巧和合理的阅读顺序,充分了解Spark的设计思想和运行机理) 许鹏 著   ISBN 978-7-121-25420- ...

  7. 《Apache Spark源码剖析》

    Spark Contributor,Databricks工程师连城,华为大数据平台开发部部长陈亮,网易杭州研究院副院长汪源,TalkingData首席数据科学家张夏天联袂力荐1.本书全面.系统地介绍了 ...

  8. TreeMap就这么简单【源码剖析】

    前言 声明,本文用得是jdk1.8 前面章节回顾: Collection总览 List集合就这么简单[源码剖析] Map集合.散列表.红黑树介绍 HashMap就是这么简单[源码剖析] LinkedH ...

  9. ConcurrentHashMap基于JDK1.8源码剖析

    前言 声明,本文用的是jdk1.8 前面章节回顾: Collection总览 List集合就这么简单[源码剖析] Map集合.散列表.红黑树介绍 HashMap就是这么简单[源码剖析] LinkedH ...

随机推荐

  1. 超级详细的git使用指北

    原文地址:https://www.cnblogs.com/wupeixuan/p/11947343.html 1.0  安装和配置 1.1  Git 安装 1.2  Git 配置 2.0  Git 基 ...

  2. win7“您可能没有权限使用网络资源”的解决办法

    删除“拒绝从网络访问这台计算机”里面的Gu   1 在屏幕的左下角点开[开始]----在搜索程序和文件那个文本框里输入[输入gpedit.msc]然后回车. 2 弹出如下图的对话框, 3 依次展开-- ...

  3. nginx 配置的server_name参数

    nginx中的server_name指令主要用于配置基于名称虚拟主机. 一 匹配顺序,server_name指令在接到请求后的匹配顺序如下: 1.确切的server_name匹配,例如: server ...

  4. 根据数据文件自定义边界条件timeVaryingUniformFixedValue【转载】

    转载自:http://blog.sina.com.cn/s/blog_e256415d0101nf9j.html 在OpenFOAM中,可以创建数据文件,自定义边界条件. 下面的例子读取outletP ...

  5. kubernetes入门学习系列

    一.kubernetes基础概念 初识kubernetes kubernetes相关概念 二.kubernets架构和组件 kubernetes架构 kubernetes单Master架构 kuber ...

  6. Thingsboard开发环境搭建及编译项目

    第一部分:JDK 1,下载JDK, JDK地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133 ...

  7. Ubuntu 1604 安装配置 kafka,并配置开机自启(systemctl)

    安装 kafka 需要先安装 jdk.一.下载官网:http://kafka.apache.org/downloads.html 二.安装 安装参考:https://segmentfault.com/ ...

  8. Leetcode: Stream of Characters

    Implement the StreamChecker class as follows: StreamChecker(words): Constructor, init the data struc ...

  9. typeScript模块<四>

    /* 功能:定义一个操作数据库的库 支持 Mysql Mssql MongoDb 要求1:Mysql MsSql MongoDb功能一样 都有 add update delete get方法 注意:约 ...

  10. python动态导入模块——importlib

    当在写代码时,我们希望能够根据传入的选项设置,如args.model来确定要导入使用的是哪个model.py文件,而不是一股脑地导入 这种时候就需要用上python的动态导入模块 比如此时文件结构为: ...