迭代器概念与traits编程技法
//迭代器是一种smart pointer
template<typename T>
class ListItem
{
public:
T value() const
{
return _value;
}
ListItem* next() const
{
return _next;
}
private:
T _value;
ListItem *_next;
}; template<class T>
class List
{
public:
void insert_front(T value);
void insert_end(T value);
void display(ostream&os = cout)const;
private:
ListItem<T>*_end;
ListItem<T>*_front;
long _size;
}; //为链表设计一个迭代器,要设计迭代器,必须要对容器有足够的了解
//所以list和对应的迭代器的设计都由list的设计者实现,从而封装实现细节
template<class Item>
struct ListIter
{
Item *ptr;//保持与容器之间的一个联系,ptr是list结点指针
ListIter(Item *p = ) :ptr(p){} //迭代器行为类似指针,其中最常见的操作是内容提领和成员访问
//所以要对operator*和operator->进行重载,可参考auto_ptr的实现
Item& operator*()const
{
return *ptr;
}
//重构->,返回值必须为一个指针或可以应用 -> 操作的类型
Item* operator->()const
{
return ptr;
}
// 前增量,返回引用(迭代器对象)
ListIter& operator++()
{
ptr = ptr->next();
return *this;
}
// 后增量,返回值
ListIter operator++(int)
{
ListIter tmp = *this;
++*this;// 利用前面对++的重载
return tmp;
} bool operator==(const ListIter& i)const
{
return ptr == i.ptr;
}
bool operator!=(const ListIter& i)const
{
return ptr != i.ptr;
}
};
注意operator *和operator->的实现,operator* 返回一个引用,operator->返回值必须为一个指针或可以应用 -> 操作的类型
如何获取迭代器所指对象的类型,即如何实现类型萃取?
可以定义一个类模板用于萃取迭代器特性,模板参数是迭代器类型。迭代器内部定义一个typedef表示迭代器所指对象类型,然后在萃取模板类中使用
typedef typename I::value_type value_type;
提取类型。由于原生指针不是class,无法定义value_type,可以对萃取模板类生成特化版本。
// 如何获取迭代器所指对象的类型
template<class T>
struct MyIter
{
typedef T value_type;//迭代器所指对象类型
T *ptr;
//....
}; template<class I>
// 函数func接受一个迭代器参数,返回值是迭代器所指对象类型
// typename告诉编译器I::value_type是一个类型(嵌套从属名称),使得能够通过编译
// 此处存在问题:如果I不是个class type,就无法定义value_type
// 可以封装类型萃取类,然后针对原生指针做偏特化处理
typename I::value_type func(I ite)
{
return *ite;
} //类模板用于萃取迭代器特性,I为迭代器类型
template<class I>
struct iterator_traits
{
typedef typename I::value_type value_type;//针对class
};
//原生指针不是class,无法定义value_type
//traits可以拥有特化版本,T *为原生指针int *,则T也就是value_type为int
template<class T>
struct iterator_traits<T*>
{
typedef T value_type;//针对原生指针
}; // 萃取机完整版本(最常用到的迭代器五种类型)
// 若使容器能与STL兼容,必须要为容器的迭代器定义以下五种相应型别
template <class I>
struct iterator_traits
{
typedef typename I::iterator_category iterator_category;// 迭代器类型
typedef typename I::value_type value_type;// 迭代器所指对象的类型
typedef typename I::difference_type difference_type;// 两个迭代器之间的距离
typedef typename I::pointer pointer;// 迭代器所指对象的指针
typedef typename I::reference reference;// 迭代器所指对象的引用
}; /*
迭代器有五种类型,Input Iterator,output Iterator,Forward Iterator只支持++,Biderectional Iterator支持++、--,Random Access Iterator支持
所有运算,效率最高
*/
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{};
//第三参数,使如下函数形成重载
template <class InputIterator,class Distance>
inline void _advance(InputIterator& i, Distance n, input_iterator_tag)
{
while (n--)
i++;
}
//下面四个函数类似,不再详述
//对外开放的接口, iterator_traits<InputIterator>::iterator_category()将产生一个暂时对象,编译器根据对象
//类型决定调用哪一个_advance重载函数
//STL一个命名规则:以算法所能接受的最低阶迭代器类型来为其迭代器类型参数命名
template<class InputIterator,class Distance>
inline void advance(InputIterator& i, Distance n)
{
_advance(i, n, iterator_traits<InputIterator>::iterator_category());
}
为了符合规范,任何迭代器都应该提供五个内嵌类型,以用于traits萃取,否则可能无法与其他STL组件顺利搭配。STL提供了一个iterators class如下,可让每个新设计的迭代器都继承自它。
//ptrdiff_t为c++内建类型,定义于<cstddef>
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;
};
迭代器概念与traits编程技法的更多相关文章
- STL源码分析读书笔记--第三章--迭代器(iterator)概念与traits编程技法
1.准备知识 typename用法 用法1:等效于模板编程中的class 用法2:用于显式地告诉编译器接下来的名称是类型名,对于这个区分,下面的参考链接中说得好,如果编译器不知道 T::bar 是类型 ...
- 迭代器iterator和traits编程技法
前言 这段时间研读SGI-STL-v2.91源码,并提炼核心代码自己实现一遍,感觉受益颇深.觉得有必要写一些文章记录下学习过程的思考,行文旨在总结,会大量参考侯捷<STL源码剖析>的内容. ...
- 迭代器(iterator) 与 traits 编程技法
看了候哥的<STL源码剖析>的迭代器那一章,在这里将思路稍微疏理一下 迭代器 迭代器模式的定义:提供一种方法,在不需要暴露某个容器的内部表现形式情况下,使之能依次访问该容器中的各个元素. ...
- STL——迭代器与traits编程技法
一.迭代器 1. 迭代器设计思维——STL关键所在 在<Design Patterns>一书中对iterator模式定义如下:提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素 ...
- 【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法
大家好,我是小贺. 点赞再看,养成习惯 文章每周持续更新,可以微信搜索「herongwei」第一时间阅读和催更,本文 GitHub : https://github.com/rongweihe/Mor ...
- STL源码--iterator和traits编程技法
第一部分 iterator学习 STL iterators定义: 提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表达方式. 任何iteartor都应该提供5 ...
- STL Traits编程技法
traits编程技法大量运用于STL实现中.通过它在一定程度上弥补了C++不是强型别语言的遗憾,增强了C++关于型别认证方面的能力. traits编程技法是利用“内嵌型别”的编程技法和编译器的temp ...
- STL中的Traits编程技法
最近在看读<STL源码剖析>,看到Traits编程技法这节时,不禁感慨STL源码作者的创新能力.那么什么是Traits编程技法呢?且听我娓娓道来: 我们知道容器的许多操作都是通过迭代器展开 ...
- [转]Traits 编程技法+模板偏特化+template参数推导+内嵌型别编程技巧
STL中,traits编程技法得到了很大的应用,了解这个,才能一窥STL奥妙所在. 先将自己所理解的记录如下: Traits技术可以用来获得一个 类型 的相关信息的. 首先假如有以下一个泛型的迭代器类 ...
随机推荐
- 410 Split Array Largest Sum 分割数组的最大值
给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组.设计一个算法使得这 m 个子数组各自和的最大值最小.注意:数组长度 n 满足以下条件: 1 ≤ n ≤ 1000 ...
- Canvas入门笔记-实现极简画笔
今天学习了Html5 Canvas入门,已经有大神写得很详细了http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html#8 在学习过后 ...
- js一键导出Excel
HTML: 1 <div class="container"> 2 <table id="backViewTable" class=" ...
- myeclipse中js文件报错
这几天在myeclipse中添加文件时,会报错,但是代码是从官网上下载的,没有错误,只是myeclipse的检查较为严格.在网上找到解决方案,希望可以帮到强迫症的人. 解决步骤: 1.window→P ...
- IIS配置负载均衡
一.下载Nginx安装包 二.修改nginx.conf文件信息 如图: 三.重新加载Nginx (nginx -s reload) 启动Nginx: start nginx 停止Nginx:nginx ...
- Java常见问题总结(二)
1.配置完Java环境变量之后,仍然不能使用java命令. 解决方法: 如果是Windows10系统出现此问题,是因为个别Windows10系统不识别“JAVA_HOME”环境变量,将path中所有的 ...
- springboot运行模式
1.springboot项目常见的运行方式: 2.说明: idea:在开发环境中跑项目,也就是我们在编码过程中的用的做多的方式 jar.war:线上.服务器上执行jar.war包的方式 maven插 ...
- 关于Python多线程condition变量的应用
''' 所谓条件变量,即这种机制是在满足了特定的条件后,线程才可以访问相关的数据. 它使用Condition类来完成,由于它也可以像锁机制那样用,所以它也有acquire方法和release方法,而且 ...
- Jsp页面,结果集分页和sql(top)分页的性能对比
jsp页面两种分页模式: 第一种: 结果集分页,主要代码见下面: ResultSet rs=stmt.executeQuery(sql); ResultSetMetaData md=rs.getMet ...
- SQL server 上机练习题
首先创建一个数据库,里面有 登录表 学生表 课程表 选课表 成绩表 1. 查询Student表中的所有记录的Sname.Ssex和Class列.2. 查询教师所有的单位即不重复的Depart列 ...