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_iterator
template<class container>
class cgh_back_insert_iterator{
protected:
container* ctr; // 配接器的底层容器
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void referenc;
/* 构造函数 */
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_iterator
template<class container>
class cgh_front_insert_iterator{
protected:
container* ctr; // 配接器的底层容器
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void referenc;
/* 构造函数 */
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_iterator
template<class container>
class cgh_insert_iterator{
protected:
container* ctr; // 配接器的底层容器
typename container::iterator iter; // 底层容器的迭代器
public:
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void referenc;
/* 构造函数 */
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::iterator iter;
return cgh_insert_iterator<container>(x, iter(i));
}
#pragma endregion
#pragma region cgh_reverse_iterator
template<class iterator>
class cgh_reverse_iterator{
protected:
iterator current; // 正向迭代器
public:
typedef typename std::iterator_traits<iterator>::iterator_category iterator_category;
typedef typename std::iterator_traits<iterator>::value_type value_type;
typedef typename std::iterator_traits<iterator>::difference_type difference_type;
typedef typename std::iterator_traits<iterator>::pointer pointer;
typedef typename std::iterator_traits<iterator>::reference reference;
typedef iterator iterator_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 endregion
iterator_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 ;
}
测试结果如下图所示