迭代器概念与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技术可以用来获得一个 类型 的相关信息的. 首先假如有以下一个泛型的迭代器类 ...
随机推荐
- 375 Guess Number Higher or Lower II 猜数字大小 II
我们正在玩一个猜数游戏,游戏规则如下:我从 1 到 n 之间选择一个数字,你来猜我选了哪个数字.每次你猜错了,我都会告诉你,我选的数字比你的大了或者小了.然而,当你猜了数字 x 并且猜错了的时候,你需 ...
- jQuery实现文字横向滚动效果
HTML代码: <div id="aaa" style="width:100px; position:relative; white-space:nowrap; o ...
- (9)string对象上的操作2
比较string对象的比较运算符 这种由string类定义的几种比较字符串的运算符能逐一比较string对象中的字符(对大小写敏感).
- C# datagrideview插件的使用
private void btnLogin_Click(object sender, EventArgs e) { string txtUserName = this.txtUserName.Text ...
- JAVA 学习笔记 - 基础语法 2
---恢复内容开始--- 1.数组的申明和应用 数据类型 数组名称[] = null; //在堆栈中申明变量名称 数组名称 = new 数据类型[10]; // ...
- C语言中结构体大小计算
1.普通结构体 struct student { char sex; char a; char b; int age; char name[100]; }; 该结构体大小为108 解答:1.先算str ...
- 网络编程基础_4.1TCP_服务端
TCP_服务端 #include <stdio.h> // 1. 包含必要的头文件和库, 必须位于 windows之前 #include <WinSock2.h> #pragm ...
- 【windows】自动化测试持续集成(CI)环境部署
1. 环境准备 1.1 我的环境 1.Win10 64位 2.JDK 1.8.0_121 3.Tomcat 7.0.92 4. Jenkins 2.24 5.SVN-Server 3.8.1 1.2 ...
- CAD使用SetxDataLong写数据(网页版)
主要用到函数说明: MxDrawEntity::SetxDataLong 写一个long扩展数据,详细说明如下: 参数 说明 [in] BSTR val 字符串值 szAppName 扩展数据名称 n ...
- 日常开发需要掌握的Git命令
本人待的两家公司,一直都是用的SVN,Git我只是自己私下学习和开发小项目的时候用过,工作一直没有使用过,但还是要学的... Git是最好的分布式版本控制系统 工作流程 SVN和Git的区别 SVN是 ...