STL 简单 iterator adapters 的实现

来源:互联网 发布:淘宝二手苹果 编辑:程序博客网 时间:2024/05/01 22:48

1. 简介

配接器(adapters)在STL组件的灵活组合上,扮演者轴承、转换的角色。Adapters事实上是一种设计模式(design pattern)。


百度百科对adapters模式的解释:

将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作——Gang of Four


         在STL的体系中,有三种类型的adapters:

1.  Container adapters:应用于容器的配接器。STL提供的两个容器 queue 和 stack,实际上就是配接器,它们底层都是用的 deque,通过修饰 deque 的接口而形成另一种风貌;

2.  Iterator adapters:应用于迭代器的配接器,这是本文介绍的主角;

3.  Functor adapters:应用于仿函数(函数对象)的配接器;

 

本文介绍迭代器的配接器实现方法,下文中所述的iterator adapters 也即迭代器的配接器。


2.iterator adapters

         STL提供了许多应用于迭代器上的配接器,其中包括 insert iterator、reverse iterator 等等。C++ standard 规定它们的接口由<iterator>获得。

 


2.1 insert iterator

         Insert iterator可以将一般迭代器的赋值(assign)操作转变为插入(insert)操作。这样的配接器有三个

1.  Back_insert_iterator:从尾部插入元素;

2.  Front_insert_iterator:从头部插入元素;

3.  Insert_iterator:从任意位置插入元素;

由于以上三个 iterator adapters 的使用接口不直观,STL提供了三个相应函数 back_inserter()、front_inserter()、inserter(),以提升使用的便利性。


辅助函数

实际产生的对象

back_inserter( container& x );

back_insert_iterator<container>( x );

front_inserter( container& x );

front_insert_iterator<container>( x );

inserter( container& x );

insert_iterator<container>( x );


2.2 reverse iterator

         reverse iterator 可以逆转迭代器的行进方向,本来前进 operator++  的变成后退,本来后退 operator--  的变成前进,STL的某些算法需要从尾部开始,使用 reverse iterator 可以很方便的交换头尾和行进方向。

 


3. 设计与实现

我用VS2013写的程序(github),iterator adapters 的实现版本的位于cghSTL/version/cghSTL-0.7.2.rar

本文介绍的 iterator adapters 需要以下文件:

1.  cgh_iterator_adapters.h,本文的主角,iterator adapters 的实现,位于cghSTL/adapters/

2.  cghStl_algobase.h,测试 iterator adapters  需要用到 copy 和 copy_backward  函数,关于 copy 算法的实现,请移步:STL简单 copy 算法的实现。cghStl_algobase.h位于cghSTL/algorithms/

3.  cghDeque.h,自己实现的 deque,关于 deque 的实现,请移步:STL简单 deque 的实现。deque用于测试,cghDeque.h 位于cghSTL/sequence containers/cghDeque/

4.  test_iterator_adapters.cpp:测试 iterator adapters ,位于cghSTL/test/

 

         每一个 insert iterator 内部都维护有一个容器(必须由用户指定),容器有自己的迭代器,于是当客户端对 inset iterator 做赋值(assign)操作时,就是 inset iterator 中被转为对该容器的迭代器做插入(insert)操作,也就是说,在 insert iterator 的 operator= 操作符中调用底层容器的 push_back()(对应back_insert_iterator 配接器)、push_front()(对应 front_insert_iterator 配接器)、insert()(对应 insert_iterator 配接器)。

         所有的 iterator adapters 的代码都在 cgh_iterator_adapters.h 文件中,cgh_iterator_adapters.h位于cghSTL/adapters/我用 region 把 cgh_iterator_adapters.h 文件划分成多个模块,可以看到一共实现了四个iterator adapters,前三个与插入(insert)有关。


        


         Iterator adapters 的实现比较简单,无非是包装一下容器的迭代器,重写 operator=(),在 operator=() 中调用容器迭代器的 push_back()、push_front()  或者 insert()  函数。有疑问的地方我都做了注释,童鞋们可以根据注释来理解其工作原理。


cgh_iterator_adapters.h

/********************************************************************  Copyright(c) 2016 Chen Gonghao*  All rights reserved.**  chengonghao@yeah.net**  功能:迭代器配接器的实现******************************************************************/#ifndef _CGH_ITERATOR_ADAPTERS_H_#define _CGH_ITERATOR_ADAPTERS_H_namespace CGH{#pragma region cgh_back_insert_iteratortemplate<class container>class cgh_back_insert_iterator{protected:container* ctr; // 配接器的底层容器public:typedef output_iterator_tagiterator_category;typedef voidvalue_type;typedef voiddifference_type;typedef voidpointer;typedef voidreferenc;/* 构造函数 */explicit cgh_back_insert_iterator(container& x) : ctr(&x) { }cgh_back_insert_iterator<container>&operator=(const typename container::value_type& value){// 这里是理解的关键// copy 函数的 *result = *first,result 的类型就是这里的 cgh_back_insert_iterator// cgh_back_insert_iterator 重写了 operator=// copy::*result = *first ----> ctr->push_back(value);ctr->push_back(value);return *this;}cgh_back_insert_iterator<container>& operator*() { return *this; }cgh_back_insert_iterator<container>& operator++() { return *this; }cgh_back_insert_iterator<container>& operator++(int) { return *this; }};/* 辅助函数,方便我们使用 cgh_back_insert_iterator */template<class container>inline cgh_back_insert_iterator<container> cgh_back_inserter(container& x){return cgh_back_insert_iterator<container>(x);}#pragma endregion#pragma region cgh_front_insert_iteratortemplate<class container>class cgh_front_insert_iterator{protected:container* ctr; // 配接器的底层容器public:typedef output_iterator_tagiterator_category;typedef voidvalue_type;typedef voiddifference_type;typedef voidpointer;typedef voidreferenc;/* 构造函数 */explicit cgh_front_insert_iterator(container& x) : ctr(&x) { }cgh_front_insert_iterator<container>&operator=(const typename container::value_type& value){// 这里是理解的关键// copy 函数的 *result = *first,result 的类型就是这里的 cgh_front_insert_iterator// cgh_front_insert_iterator 重写了 operator=// copy::*result = *first ----> ctr->push_front(value);ctr->push_front(value);return *this;}cgh_front_insert_iterator<container>& operator*() { return *this; }cgh_front_insert_iterator<container>& operator++() { return *this; }cgh_front_insert_iterator<container>& operator++(int) { return *this; }};/* 辅助函数,方便我们使用 cgh_front_insert_iterator */template<class container>inline cgh_front_insert_iterator<container> cgh_front_inserter(container& x){return cgh_front_insert_iterator<container>(x);}#pragma endregion#pragma region cgh_insert_iteratortemplate<class container>class cgh_insert_iterator{protected:container* ctr; // 配接器的底层容器typename container::iteratoriter; // 底层容器的迭代器public:typedef output_iterator_tagiterator_category;typedef voidvalue_type;typedef voiddifference_type;typedef voidpointer;typedef voidreferenc;/* 构造函数 */explicit cgh_insert_iterator(container& x, typename container::iterator i) : ctr(&x), iter(i) { }cgh_insert_iterator<container>&operator=(const typename container::value_type& value){// 这里是理解的关键// copy 函数的 *result = *first,result 的类型就是这里的 cgh_insert_iterator// cgh_insert_iterator 重写了 operator=// copy::*result = *first ----> ctr->insert(iter, value);iter = ctr->insert(iter, value);++iter;return *this;}cgh_insert_iterator<container>& operator*() { return *this; }cgh_insert_iterator<container>& operator++() { return *this; }cgh_insert_iterator<container>& operator++(int) { return *this; }};/* 辅助函数,方便我们使用 cgh_insert_iterator */template<class container, class iterator>inline cgh_insert_iterator<container> cgh_inserter(container& x, iterator i){typedef typename container::iteratoriter;return cgh_insert_iterator<container>(x, iter(i));}#pragma endregion#pragma region cgh_reverse_iteratortemplate<class iterator>class cgh_reverse_iterator{protected:iterator current; // 正向迭代器public:typedef typename std::iterator_traits<iterator>::iterator_categoryiterator_category;typedef typename std::iterator_traits<iterator>::value_typevalue_type;typedef typename std::iterator_traits<iterator>::difference_typedifference_type;typedef typename std::iterator_traits<iterator>::pointerpointer;typedef typename std::iterator_traits<iterator>::referencereference;typedef iteratoriterator_type; // 代表正向迭代器typedef cgh_reverse_iterator<iterator>self; // 代表反向迭代器public:#pragma region 构造函数cgh_reverse_iterator(){}explicit cgh_reverse_iterator(iterator_type x) : current(x){}cgh_reverse_iterator(const self& x) : current(x.current){}#pragma endregioniterator_type base() const{return current;}/* 指针解除引用 */reference operator*()const{iterator tmp = current;// 这里是理解的关键// 对逆向迭代器取值,就是将“对应的正向迭代器”后退一格,然后取值return *--tmp;}pointer operator->() const{return &(operator*());}self& operator++(){// current 记录的是正向迭代器// 逆向迭代器的 ++ 就是正向迭代器的 ----current;return *this;}self operator++(int){self tmp = *this;--current;return tmp;}self& operator--(){// current 记录的是正向迭代器// 逆向迭代器的 -- 就是正向迭代器的 ++++current;return *this;}self operator--(int){self tmp = *this;++current;return tmp;}self operator+(difference_type n) const{return self(current - n);}self& operator+=(difference_type n){current -= n;return *this;}self operator-(difference_type n) const{return self(current + n);}self& operator-=(difference_type n){current += n;return *this;}reference operator[](difference_type n) const{return *(*this + n);}};#pragma endregion};#endif


 

4.测试

         测试的内容已在注释中给出。

test_iterator_adapters.cpp

/********************************************************************  Copyright(c) 2016 Chen Gonghao*  All rights reserved.**  chengonghao@yeah.net**  功能:测试迭代器配接器******************************************************************/#include "stdafx.h"#include <iostream>#include "cghDeque.h"#include "cgh_iterator_adapters.h"#include "cghStl_algobase.h"int _tmain(int argc, _TCHAR* argv[]){using namespace CGH;//////////////////////////////////////////////////////////////////////////////////////////////////////// 测试 cgh_back_inserter/////////////////////////////////////////////////////////////////////////////////////////////////////std::cout << std::endl << "************************ 测试 cgh_back_inserter ***************************" << std::endl;cghDeque<int> deque1;deque1.push_back(1);deque1.push_back(2);deque1.push_back(3);deque1.push_back(4);deque1.push_back(5);cghDeque<int> deque2;deque2.push_back(6);deque2.push_back(7);deque2.push_back(8);deque2.push_back(9);deque2.push_back(10);std::cout << std::endl << "现有 deque1 = { 1, 2, 3, 4, 5 }; \n     deque2 = { 6, 7, 8, 9, 10 };" << std::endl << std::endl;std::cout << "调用:copy(test2.begin(), test2.end(), cgh_back_inserter(test1));\n\n把 deque2 插入到 deque1 的后面,插入结果:" ;copy(deque2.begin(), deque2.end(), cgh_back_inserter(deque1));for (int i = 0; i < deque1.size(); ++i){std::cout << deque1[i] << ", ";}std::cout << std::endl << std::endl;//////////////////////////////////////////////////////////////////////////////////////////////////////// 测试 cgh_front_inserter/////////////////////////////////////////////////////////////////////////////////////////////////////std::cout << std::endl << "************************ 测试 cgh_front_inserter ***************************" << std::endl;cghDeque<int> deque3;deque3.push_back(1);deque3.push_back(2);deque3.push_back(3);deque3.push_back(4);deque3.push_back(5);cghDeque<int> deque4;deque4.push_back(6);deque4.push_back(7);deque4.push_back(8);deque4.push_back(9);deque4.push_back(10);std::cout << std::endl << "现有 deque3 = { 1, 2, 3, 4, 5 }; \n     deque4 = { 6, 7, 8, 9, 10 };" << std::endl << std::endl;std::cout << "调用:copy(deque4.begin(), deque4.end(), cgh_front_inserter(deque3));\n\n把 deque4 插入到 deque3 的前面,插入结果:" ;copy(deque4.begin(), deque4.end(), cgh_front_inserter(deque3));for (int i = 0; i < deque3.size(); ++i){std::cout << deque3[i] << ", ";}std::cout << std::endl << std::endl;//////////////////////////////////////////////////////////////////////////////////////////////////////// 测试 cgh_inserter/////////////////////////////////////////////////////////////////////////////////////////////////////std::cout << std::endl << "************************ 测试 cgh_inserter ***************************" << std::endl;cghDeque<int> deque5;deque5.push_back(1);deque5.push_back(2);deque5.push_back(3);deque5.push_back(4);deque5.push_back(5);cghDeque<int> deque6;deque6.push_back(6);deque6.push_back(7);deque6.push_back(8);deque6.push_back(9);deque6.push_back(10);std::cout << std::endl << "现有 deque5 = { 1, 2, 3, 4, 5 }; \n     deque6 = { 6, 7, 8, 9, 10 };" << std::endl << std::endl;std::cout << "调用:\n   copy(deque6.begin(), deque6.end(), cgh_inserter(deque5, deque5.begin() + 3));\n把 deque6 插入到 1, 2, 3,_这里_, 4, 5,插入结果:" ;copy(deque6.begin(), deque6.end(), cgh_inserter(deque5, deque5.begin() + 3));for (int i = 0; i < deque5.size(); ++i){std::cout << deque5[i] << ", ";}std::cout << std::endl << std::endl;//////////////////////////////////////////////////////////////////////////////////////////////////////// 测试 cgh_reverse_iterator/////////////////////////////////////////////////////////////////////////////////////////////////////std::cout << std::endl << "************************ 测试 cgh_reverse_iterator ***************************" << std::endl;cghDeque<int> deque7;deque7.push_back(1);deque7.push_back(2);deque7.push_back(3);deque7.push_back(4);deque7.push_back(5);std::cout << std::endl << "现有 deque7 = { 1, 2, 3, 4, 5 };" << std::endl << std::endl;std::cout << "测试反向输出 deque7 :" ;cghDeque<int>::reverse_iterator reverse_iter(deque7.rbegin());for (int i = 0; i < 5; ++i, ++reverse_iter){std::cout << *reverse_iter << ", ";}std::cout << std::endl << std::endl;system("pause");return 0 ;}



测试结果如下图所示


0 0
原创粉丝点击