STL源码剖析——iterators与trait编程#4 iterator源码
在前两节介绍了迭代器的五个相应类型,并讲述如何利用traits机制提取迭代器的类型,但始终是把iteartor_traits类分割开来讨论,这影响我们的理解,本节将给出iteator的部分源码,里面涵盖了整个iteartor_traits泛化版本、偏特化版本以及一些算法的完整代码。重新把先前讲的知识捋顺一下。
//节选自SGI STL<stl_iterator.h> //五种迭代器类型,继承表示,越底层的基类越低级,越上层的子类越高级
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {}; //要使自己设计的迭代器符合STL的规范,最好继承自下面的std::iterator
template <class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&>
struct iterator {
typedef Category iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
}; //提取迭代器五个相应类型的榨汁机iterator_traits,可以看到迭代器其特性均来自迭代器本身,说明设计迭代器时候就应该考虑提供这五个相应类型。所以为了防止自己设计时有所遗漏,继承std::iterator是上策
template <class Iterator>
struct iterator_traits {
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};
//针对原生指针而设计的traits偏特化版本
template <class T>
struct iterator_traits<T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
//针对原生pointer-to-const而设计的traits偏特化版本
template <class T>
struct iterator_traits<const T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
};
//全局函数,这个函数可以很方便地决定某个迭代器的类型
template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&) {
typedef typename iterator_traits<Iterator>::iterator_category category; //使用traits机制提取其iterator category
return category();
}
//全局函数,这个函数可以很方便地决定某个迭代器的distance type
template <class Iterator>
inline typename iterator_traits<Iterator>::difference_type*
distance_type(const Iterator&) {
return static_cast<typename iterator_traits<Iterator>::difference_type*>();
}
//全局函数,这个函数可以很方便地决定某个迭代器的value type
template <class Iterator>
inline typename iterator_traits<Iterator>::value_type*
value_type(const Iterator&) {
return static_cast<typename iterator_traits<Iterator>::value_type*>();
} //整组distance函数,该函数有计算两迭代器距离的功能
template <class InputIterator, class Distance>
inline void __distance(InputIterator first, InputIterator last, Distance& n,
input_iterator_tag) { //如果是非随机迭代器,只能每次循环都要判断是否到达last迭代器
while (first != last) { ++first; ++n; }
} template <class RandomAccessIterator, class Distance>
inline void __distance(RandomAccessIterator first, RandomAccessIterator last,
Distance& n, random_access_iterator_tag) { //随机迭代器,不用做两迭代器是否相同的比较,由于提供了operator-(),直接减法处理,速度比前者快
n += last - first;
} template <class InputIterator, class Distance>
inline void distance(InputIterator first, InputIterator last, Distance& n) {
__distance(first, last, n, iterator_category(first)); //使用上面提到的iterator_category()全局函数决定哪个迭代器类型
} //以下是整组advance函数,该函数具有从某迭代器出发跳跃到指定距离位置的功能
template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
while (n--) ++i; //使用非随机单向迭代器,只能逐次前进至指定位置
} template <class BidirectionalIterator, class Distance>
inline void __advance(BidirectionalIterator& i, Distance n,
bidirectional_iterator_tag) { //使用双向迭代器,可能往前或往后移动,但也是只能逐次移动至指定位置
if (n >= )
while (n--) ++i;
else
while (n++) --i;
} template <class RandomAccessIterator, class Distance>
inline void __advance(RandomAccessIterator& i, Distance n,
random_access_iterator_tag) { //随机迭代器,真正的跳跃
i += n;
} template <class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n) {
__advance(i, n, iterator_category(i)); //使用上面提到的iterator_category()全局函数决定哪个迭代器类型
}
STL源码剖析——iterators与trait编程#4 iterator源码的更多相关文章
- STL源码剖析——iterators与trait编程#2 Traits编程技法
在算法中运用迭代器时,很可能用到其相应类型.什么是相应类型?迭代器所指对象的类型便是其中一个.我曾有一个错误的理解,那就是认为相应类型就是迭代器所指对象的类型,其实不然,相应类型是一个大的类别,迭代器 ...
- STL源码剖析——iterators与trait编程#3 iterator_category
最后一个迭代器的相应类型就是iterator_category,就是迭代器本身的类型,根据移动特性与实行的操作,迭代器被分为了五类: Input Iterator:这种迭代器所指的对象,不允许外界改变 ...
- STL源码剖析——iterators与trait编程#1 尝试设计一个迭代器
STL的中心思想在于:将数据容器与算法分开,独立设计,再用一帖粘着剂将它们撮合在一起.而扮演粘着剂这个角色的就是迭代器.容器和算法泛型化,从技术角度来看并不困难,C++的模板类和模板函数可分别达成目标 ...
- STL源码剖析——Iterators与Traits编程#5 __type_traits
上节给出了iterator_traits以及用到traits机制的部分函数的完整代码,可以看到traits机制能够提取迭代器的特性从而调用不同的函数,实现效率的最大化.显然这么好的机制不应该仅局限于在 ...
- 《python解释器源码剖析》第8章--python的字节码与pyc文件
8.0 序 我们日常会写各种各样的python脚本,在运行的时候只需要输入python xxx.py程序就执行了.那么问题就来了,一个py文件是如何被python变成一系列的机器指令并执行的呢? 8. ...
- Apache Spark源码剖析
Apache Spark源码剖析(全面系统介绍Spark源码,提供分析源码的实用技巧和合理的阅读顺序,充分了解Spark的设计思想和运行机理) 许鹏 著 ISBN 978-7-121-25420- ...
- 《Apache Spark源码剖析》
Spark Contributor,Databricks工程师连城,华为大数据平台开发部部长陈亮,网易杭州研究院副院长汪源,TalkingData首席数据科学家张夏天联袂力荐1.本书全面.系统地介绍了 ...
- TreeMap就这么简单【源码剖析】
前言 声明,本文用得是jdk1.8 前面章节回顾: Collection总览 List集合就这么简单[源码剖析] Map集合.散列表.红黑树介绍 HashMap就是这么简单[源码剖析] LinkedH ...
- ConcurrentHashMap基于JDK1.8源码剖析
前言 声明,本文用的是jdk1.8 前面章节回顾: Collection总览 List集合就这么简单[源码剖析] Map集合.散列表.红黑树介绍 HashMap就是这么简单[源码剖析] LinkedH ...
随机推荐
- Python之pygame学习绘制文字制作滚动文字
pygame绘制文字 ✕ 今天来学习绘制文本内容,毕竟游戏中还是需要文字对玩家提示一些有用的信息. 字体常用的不是很多,在pygame中大多用于提示文字,或者记录分数等事件. 字体绘制基本分为以下几个 ...
- 10分钟彻底理解Redis持久化和主从复制
在这篇文章,我们一起了解 Redis 使用中非常重要的两个机制:Reids 持久化和主从复制. 什么是 Redis 持久化? Redis 作为一个键值对内存数据库(NoSQL),数据都存储在内存当中, ...
- How to Hack Unity Games using Mono Injection Tutorial
https://guidedhacking.com/threads/how-to-hack-unity-games-using-mono-injection-tutorial.11674/ Unity ...
- 【转】python requests库添加自定义cookie的方法
requests库是个很方便的爬虫,相关文档已经很详细了.不过我今天在爬网页时,有一个网站是在脚本中添加cookie的,但我向requests.cookies里添加cookie费了不少周折.尝试了多个 ...
- OpenGL ES: (5) OpenGL的基本概念、OpenGL ES 在屏幕产生图片的过程、OpenGL管线(pipeline)
一. OpenGL的基本概念 OpenGL 的结构可以从逻辑上划分为下面 3 个部分: 图元(Primitives) 缓冲区(Buffers) 光栅化(Rasterize) 图元(Primitives ...
- Code Quality and Security | SonarQube
SonarQube - 国内版 Binghttps://cn.bing.com/search?FORM=U227DF&PC=U227&q=SonarQube Code Quality ...
- Tomcat connection & session timeout settings
# connection timeout for globle web application cat /home/soft/apache-tomcat-7.0.92/conf/server.xml ...
- Typora的日常使用方法
原文地址:https://www.jianshu.com/p/a6a6a22e9393 ” Markdown 是一种轻量级标记语言,创始人是约翰·格鲁伯(John Gruber).它允许人们 “使用易 ...
- 详解 C++11 lambda表达式
详解 C++11 lambda表达式 lambda表达式是函数式编程的基础.咱对于函数式编程也没有足够的理解,因此这里不敢胡言乱语,有兴趣的可以自己查找相关资料看下.这里只是介绍C++11中的la ...
- 青葱的岁月 Mybatis JdbcType与Oracle、MySql数据类型对应列表
Mybatis JdbcType Oracle MySql JdbcType ARRAY JdbcType BIGINT BIGINT JdbcType BINARY JdbcTy ...