Boost库迭代器
来源:互联网 发布:淘宝申请开网店要多久 编辑:程序博客网 时间:2024/06/08 13:35
《C++11/14高级编程:Boost程序库探秘》笔记
迭代器模式
”提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示“
C++标准(C++11.24.2)将迭代器分为五类:输入迭代器(只读迭代器)、输出迭代器(只写迭代器)、前向迭代器(可以读写,提供operator++,可以执行相等比较和赋值操作)、双向迭代器(在前向基础上增加了operator- -)、随机访问迭代器(在双向基础上增加了迭代器的算术运算功能,提供operator[]和operator+=)。
iterators库定义了一组基于标准库的新的迭代器概念、构造框架和有用的适配器。首先,区分了迭代器的值访问概念和遍历概念,重新划分了迭代器的类型。
根据值访问方式,迭代器分为四类:
- 可读迭代器:提供operator*,可返回可转换为类型T的右值。
- 可写迭代器:提供operator*,可以执行赋值操作(不一定是左值)。
- 可交换迭代器:两个迭代器所指的值可用标准库的iter_swap()函数交换,即同时满足可读和可写的要求。
- 左值迭代器:满足可交换迭代器,并且operator*可返回左值,即类型T的引用。
根据遍历方式,迭代器分五类:
- 可递增迭代器:提供operator++,可拷贝构造和赋值
- 单遍迭代器:增加operator==、operator!=比较操作
- 前向遍历迭代器:增加difference_type类型定义,可计算距离和缺省构造
- 双向遍历迭代器:增加operator- -,可以逆向遍历
- 随机访问遍历迭代器:增加迭代器的算术运算和比较运算,并提供operator[]。
标准库提供了三个迭代器辅助函数(C++11.24.4.4)
- advance(pos,n):使迭代器前进或后退n个位置
- distance(p1,p2):计算两个迭代器间的距离
- iter_swap():交换两个迭代器所指的元素的值
这三个辅助函数能够以统一的方式操作迭代器,无须关心迭代器的类别。
标准库提供了一些迭代器适配器,可以把一种迭代器转换为另一种迭代器(C++11.24.5)
- 逆向迭代器:适配后迭代器可以逆序迭代
- 转移迭代器:C++11/14新增的迭代器适配器,迭代器返回右值引用
- 插入迭代器:把赋值操作转换为执行插入操作的输出迭代器
- 流迭代器:把IO流转换为迭代器操作
next_prior
next_prior组件提供了两个非常简单易用的模板函数next()和prior(),使用了迭代器辅助工具advance()为仅提供operator++和operator–的迭代器增加了前向或后向N步的通用解法,其实就是用封装了一层advance()。
template<class T>inline T next(T x) //单参形式{ return ++x;}template<class T,class Distance>inline T next(T x, Distance n) //双参形式{ std::advance(x, n); return x;}template<class T>inline T prior(T x) //单参形式{ return --x;}template<class T, class Distance>inline T prior(T x, Distance n) //双参形式{ std::advance(x, -n); return x;}
advance()会自动根据迭代器的类型采取最有效率的步进措施——对于随机访问迭代器直接调用operator+=,对于其他的迭代器则循环调用递增或递减操作。
如果迭代器不提供operator++或operator- -,那么使用这两个函数会引发编译错误。
虽然这两个名字叫next和prior,但是双参版本的第二个参数可以传入负数,也就是实际上可以使迭代器任意前后移动(前提是迭代器支持operator- -)
这个组件位于名字空间boost,需要包含头文件<boost/next_prior.hpp>,即:
#include <boost/next_prior.hpp>using namespace boost;
C++11标准在头文件<iterator>里定义了std::next()和std::prev(),实现的功能相同,但声明形式略有不同:
template<class ForwardIterator>ForwardIterator next(ForwardIterator x,difference_type n = 1); //带缺省参数template<class BidirectionalIterator>BidirectionalIterator prev(BidirectionalIterator x,difference_type n = 1); //带缺省参数
iterator_traits
标准库的std::iterator_traits接受一个迭代器(或指针)类型,可以获得迭代器(或指针)所必备的五个类型信息:iterator_category(迭代器的分类)、value_type(迭代器所指的值类型)、reference(迭代器的值引用类型)、pointer(迭代器的指针类型)、difference_type(迭代器的距离类型),但是标准中把这五个类型揉成一团,从模板元编程的角度看不符合元函数的规范定义,是非标准元函数。
iterator_traits库把std::iterator_traits中揉成一团的元数据分解开来,形成了五个标准元函数,功能是完全相同的。
- iterator_category<I> :返回迭代器的分类
- iterator_value<I> :返回迭代器的值类型
- iterator_reference<I> :返回迭代器的值引用类型
- iterator_pointer<I> :返回迭代器的指针类型
- iterator_difference<I> :返回迭代器的距离类型
这五个元函数其实也是调用了标准的iterator_traits:
template<class Iterator>struct iterator_value{ typedef typename iterator_traits<Iterator>::value_type type;};
这个库位于名字空间boost,需要包含头文件<boost/iterator/iterator_traits.hpp>
iterator_facade
iterator_facade是一个重要组件,它使用外观模式提供一个辅助类,能够容易地创建符合标准的迭代器。iterator_facade定义了数个迭代器的核心接口,用户只需实现这些核心功能就可以编写正确且完备的迭代器。
iterator_facade要求用户的迭代器类必须实现下面五个功能(共六个接口,但依据迭代器的类型某些函数不实现)。
- 解引用:deference(),实现可读迭代器和可写迭代器必需
- 相等比较:equal(),实现单遍迭代器必需
- 递增:increment(),实现可递增迭代器和前向遍历迭代器必需
- 递减:decrement(),实现双向遍历迭代器必需
- 距离计算:advance()和distance_to(),实现随机访问遍历迭代器必需
这些核心操作将被iterator_facade用来实现迭代器的外部接口,所以通常它们都是private的。
为了使iterator_facade访问这些核心操作函数,库又提供了一个辅助类boost::iterator_core_access,它定义了可以访问private核心操作的若干静态成员函数,用户迭代器要把它声明为友元。
iterator_facade基于迭代器核心操作实现迭代器功能,类摘要如下:
template< class Derived, //子类的名字,用户正在编写的自己的迭代器 class Value, //迭代器的值类型 class CategoryOrTraversal, //迭代器的分类 class Reference = Value&, class Difference = ptrdiff_t,>class iterator_facade{public: //迭代器各种必需的类型定义 typedef remove_const<Value>::type value_type; typedef Reference reference; typedef Value* pointer; typedef Difference difference_type; typedef some_define iterator_category; //迭代器的各种操作定义 Reference operator*() const; some_define operator->() const; some_define operator[](difference_type n) const; Derived& operator++(); Derived operator++(int); Derived& operator--(); Derived operator--(int); Derived& operator+=(difference_type n); Derived& operator-=(difference_type n); Derived operator-(difference_type n) const;};
示例一
编写一个可写单遍迭代器
template<typename T>class vs_iterator : public boost::iterator_facade< //基类链技术继承 vs_iterator<T>, T, //子类名和值类型 boost::single_pass_traversal_tag> //单遍迭代器类型{private: std::vector<T>& v; //容器的引用 size_t current_pos; //迭代器的当前位置public: typedef boost::iterator_facade<vs_iterator<T>, T,boost::single_pass_traversal_tag> super_type; typedef vs_iterator this_type; //定义自身的别名 typedef typename super_type::reference reference; //使用基类的引用类型 vs_iterator(std::vector<T> &_v,size_t pos = 0) : v(_v), current_pos(pos) {} vs_iterator(this_type const& other) : v(other.v), current_pos(other.current_pos) {} void operator=(this_type const& other) { this->v = other.v; this->current_pos = other.current_pos; }private: friend class boost::iterator_core_access; //必需的友元声明 reference dereference() const //解引用操作 { return v[current_pos]; } void increment() //递增操作 { ++current_pos; } bool equal(this_type const& other) const //比较操作 { return this->current_pos == other.current_pos; }};int main(){ std::vector<int> v{ 1,2,3,4,5 }; vs_iterator<int> vsi(v), vsi_end(v, v.size()); *vsi = 9; std::copy(vsi, vsi_end, std::ostream_iterator<int>(std::cout, ",")); return 0;}
示例二
定义一个每次跳跃式前进N个位置的步进迭代器step_iterator:
template<typename T,std::ptrdiff_t N = 2> //缺省一次前进两步class step_iterator : public boost::iterator_facade< //基类链技术继承 step_iterator<T>, //子类名 typename boost::iterator_value<T>::type const, //元函数获得值类型 boost::single_pass_traversal_tag> //单遍迭代器类型{private: T m_iter; //迭代器位置public: typedef boost::iterator_facade<step_iterator<T>, typename boost::iterator_value<T>::type const, boost::single_pass_traversal_tag> super_type; typedef step_iterator this_type; //定义自身的别名 using typename super_type::reference; //使用基类的引用类型 step_iterator(T x) :m_iter(x) {} step_iterator(this_type const& other) = default; //拷贝构造,使用default this_type& operator=(this_type const& other) = default; //赋值函数private: friend class boost::iterator_core_access; //必需的友元声明 reference dereference() const //解引用操作 { return *m_iter; } void increment() //递增操作 { std::advance(m_iter,N); } bool equal(this_type const& other) const //比较操作 { return m_iter == other.m_iter; }};int main(){ char s[] = "12345678"; std::copy(s, s + 8, std::ostream_iterator<char>(std::cout)); step_iterator<char*> first(s), last(s + 8); //用char*迭代,默认步长2 std::copy(first, last, std::ostream_iterator<char>(std::cout)); return 0;}
iterator_adaptor
iterator_adaptor基于对象适配器模式,主要功能就是把已经存在的类型适配为一个新的迭代器。
iterator_adaptor派生自iterator_facade,同样使用了基类链技术,类摘要如下:
template< class Derived, //迭代器子类名 class Adaptee, //被适配的迭代器 class Value = use_default, //值类型 class CategoryOrTraversal = use_default, //迭代器分类标志 class Reference = use_default, //迭代器值引用类型 class Difference = use_default, //迭代器距离类型>class iterator_adaptor : public iterator_facade<Derived, ...>{ friend class iterator_core_access; //必需的友元声明public: iterator_adaptor(); explicit iterator_adaptor(Adaptee const& iter); typedef Adaptee base_type; //被适配的原始迭代器类型定义 Adaptee const& base() const;private: //适配Adaptee实现iterator_facade必需的六个核心迭代器接口 reference dereference() const; bool equal(iterator_adaptor const& x) const; void increment(); void decrement(); void advance(typename difference_type n); difference_type distance_to(iterator_adaptor const& y) const;protected: typedef some_define iterator_adaptor_; //自身的类型定义 Adaptee const& base_reference() const; Adaptee base_reference();private: Adaptee m_iterator; //迭代器成员变量};
iterator_adaptor有六个模板参数,常用的是前两个,第一个Derived的含义同iterator_facade,也是自定义的迭代器类型,即子类;第二个Adaptee是要被适配的,已经存在的类型(可以是已经存在的迭代器,或者是任何其他类型),其他模板参数可以使用缺省值boost::use_default在编译期自动推导。
iterator_adaptor是对iterator_facade的一个具体实现,因此需要使用iterator_core_access作为友元,并借用Adaptee实现dereference()、increment()等六个核心操作。
iterator_adaptor的有参构造函数要求传入被适配的Adaptee实例,被保存在成员变量m_iterator。为了方便子类使用,base_reference()和base()可以直接获得被适配的原始迭代器对象m_iterator。
iterator_adaptor还有一个类型定义iterator_adaptor_,它是iterator_adaptor<Derived,…>自身,为了便于子类引用而不必写出一串的模板参数列表,子类代码可以直接使用。
示例一
把普通数组指针适配为迭代器接口,指针本身已经具有迭代器的操作,所以适配代码比较简单:
template<typename P> //适配任意的指针类型class array_iter : public boost::iterator_adaptor<array_iter<P>, P> //适配类型P{ BOOST_STATIC_ASSERT(is_pointer<P>::value); //静态断言保证P必须是指针public: typedef typename array_iter::iterator_adaptor_ super_type; //基类定义 array_iter(P x) :super_type(x) {}};int main(){ int a[10] = { 1,2,3 }; array_iter<int*> start(a), finish(a + 10); //两个起点和终点迭代器 start += 1; std::copy(start, finish, std::ostream_iterator<int>(std::cout, ",")); return 0;}
示例二
实现一个delta_iterator,可以访问存储增量数值的容器,类似标准算法partial_sum:
template<typename I>class delta_iterator :public boost::iterator_adaptor< delta_iterator<I>, I, typename std::iterator_traits<I>::value_type, //值类型 boost::single_pass_traversal_tag //单向遍历标志 typename std::iterator_traits<I>::value_type const> //只读迭代器{private: friend class boost::iterator_core_access; typedef delta_iterator this_type; typedef typename this_type::iterator_adaptor_ super_type; typename super_type::value_type m_value; //存储当前的值public: explicit delta_iterator(const I& iter) : super_type(iter), m_value(0) {}private: using super_type::base; using super_type::base_reference; typename super_type::reference dereference() const { return m_value + *base(); //当前值+增量 } void increment() { m_value += *base(); //计算当前值 ++base_reference(); //迭代器前进 }};int main(){ std::vector<int> a = { 1,2,3 }; //存储增量值,实际的数值是1,3,6 typedef delta_iterator<decltype(a.cbegin())> delta_iter; delta_iter start(a.begin()), finish(a.end()); return 0;}
迭代器工具
前面提到的iterator_facade和iterator_adaptor都是两个辅助类,iterators库在这两个辅助类下,实现了很多非常有用的迭代器工具,这些工具大部分位于<boost/iterator/>目录,少量位于<boost/>目录,并且都提供形如make_xxx_iterator()的工厂函数以方便使用。
1.共享容器迭代器
shared_container_iterator把一个被boost::shared_ptr管理的容器适配成迭代器的形式来操作,比直接用shared_ptr更加简单方便。
它本身几乎没有什么功能代码,仅仅是一个简单的适配,构造函数要求传入容器的迭代器和指向容器的共享指针(不是std::shared_ptr)
template <typename Container>class shared_container_iterator : public boost::iterator_adpator<shared_container_iterator<Container>, typename Container::iterator> //被适配的容器迭代器{ typedef typename Container::iterator iterator_t; typedef boost::shared_ptr<Container> container_ref_t; container_ref_t container_ref;public: shared_container_iterator() {} shared_container_iterator(iterator_t const& x, container_ref_t const& c) : super_t(x), container_ref(c) {}};//用法auto sv = boost::make_shared<vector<int> >(10); //共享容器typedef shared_container_iterator<vector<int>> sci_t;sci_t first(sv->begin(),sv);sci_t last(sv->end(),sv);std::fill(first,last,9);
为了方便使用,shared_container_iterator还提供了一个辅助函数make_shared_container_iterator(),可以直接产生shared_container_iterator: make_shared_container_iterator(iter,container);
省去写出临时变量,简化代码
std::fill( make_shared_container_iterator(sv->begin(),sv), make_shared_container_iterator(sv->end(),sv),9);
另外一个辅助函数make_shared_container_range()以pair的形式返回共享容器的两个端点,符合boost.range的概念,可以传递给使用range概念的算法
2.发生器迭代器
generator_iterator可以把一个函数或者函数对象适配成输入迭代器,每次调用operator++并解引用迭代器都会获得一个值。
generator_iterator构造函数要求传入一个发生器指针:
template<class Generator>class generator_iterator :public boost::iterator_facade< generator_iterator<Generator>, typename Generator::result_type, boost::single_pass_traversal_tag, typename Generator::result_type const& >{public: generator_iterator() {} generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {} void increment() { m_value = (*m_g)(); } const typename Generator::result_type& dereference() const { return m_value; } bool equal(generator_iterator const& y) const { return this->m_g == y.m_g && this->m_value == y.m_value; }private: Generator* m_g; typename Generator::result_type m_value;};
generator_iterator提供一个辅助函数make_generator_iterator()用于直接创建发生器迭代器,它的接口和generator_iterator的构造函数不同,不是指针而是引用:
template<class Generator>inline generator_iterator<Generator>make_generator_iterator(Generator& gen);
使用generator_iterator把随机数发生器适配成迭代器的形式
boost::rand48 rng;auto iter = make_generator_iterator(rng);for(int i = 0;i < 5; ++i){ cout << *++iter << ",";}
3.逆向迭代器
reverse_iterator把一个迭代器适配成可以逆序遍历的逆向迭代器。
reverse_iterator要求适配的迭代器必须满足双向迭代器的概念,即提供operator–。
template<class Iterator>class reverse_iterator :public boost::iterator_adaptor<reverse_iterator<Iterator>, Iterator>{public: reverse_iterator() {} explicit reverse_iterator(Iterator x) :super_t(x) {}private: typename super_t::reference dereference() const { return *boost::prior(this->base()); } void increment() { --this->base_reference(); } void decrement() { ++this->base_reference(); } void advance(typename super_t::difference_type n) { this->base_reference() += -n; }};
reverse_iterator也提供一个辅助函数make_reverse_iterator(),可以轻松创建逆向迭代器:
char s[] = "hello iterator."; std::copy( make_reverse_iterator(s + std::char_traits<char>::length(s)), make_reverse_iterator(s), std::ostream_iterator<char>(std::cout));
4.间接迭代器
indirect_iterator把一个迭代器进行适配,在执行operator*时再多执行一次解引用操作(即再执行一次operator*),适合用于查看保存指针、只能指针或者迭代器的容器。
它的类摘要没有什么特别的,直接看看用法。
同样提供工厂函数make_indirector_iterator()
std::vector<int*> v = { new int(1),new int(2) };//不适用间接迭代器访问元素for (auto pos = v.begin(); pos != v.end(); ++pos){ std::cout << **pos << ",";}//使用间接迭代器访问元素auto start = make_indirect_iterator(v.begin());auto finish = make_indirect_iterator(v.end());for (; start != finish;){ std::cout << *start++ << ",";}//需要及时删除指针避免内存泄露for_each(v.begin(), v.end(), checked_deleter<int>());
5.计数迭代器
counting_iterator把一个可递增的类型适配成迭代器,使用了元编程来计算迭代器类型等模板参数
template< class Incrementable, //可递增类型 class CategoryOrTraversal = use_default, class Difference = use_default> class counting_iterator : public boost::iterator_adaptor< counting_iterator<...> //计数迭代器自身 , Incrementable //被适配的可递增类型 , Incrementable const //值类型 , traversal //迭代器分类 , Incrementable const& //值引用类型 , difference > //迭代器距离类型{public: counting_iterator(); counting_iterator(counting_iterator const& rhs); explicit counting_iterator(Incrementable x); reference operator*() const; counting_iterator& operator++(); counting_iterator& operator--();};
counting_iterator最重要的模板参数是Incrementable,它要求是可拷贝构造和可赋值的。Incrementable必须能够执行operator++操作,如果counting_iterator是单遍迭代器、双向遍历迭代器或者随机访问遍历迭代器,则Incrementable还应具备operator==、operator–和算术运算的功能。通常Incrementable是整数,但也可以是任何符合以上要求的类型(例如迭代器)。
counting_iterator可以为一个类型增加解引用操作,把它变得像一个迭代器,对于某些需要连续增加的类型来说很有用。同样,counting_iterator提供了工厂函数make_counting_iterator()
counting_iterator<int> i(100); //把int适配成计数迭代器assert(*i++ == 100);assert(*i == 101);assert(*++i == 102);std::vector<int> v;std::copy( make_counting_iterator(0), //从0填充到9 make_counting_iterator(10), std::back_inserter(v) );
把随机数发生器包装成一个可递增的类型rand_int,符合counting_iterator对Incrementable的要求:可递增、可拷贝构造、可赋值、可比较:
template<typename R>class rand_int{private: R &r; //随机数的引用 int count; //个数统计,用于相等比较public: rand_int(R& _r, int c = 0) : r(_r), count(c) {} rand_int(rand_int const& other) = default; rand_int& operator=(rand_int const &other) = default; void operator++() { ++count; } friend bool operator==(rand_int const& l, rand_int const& r) { return l.count == r.count; } //转型到整数的操作符,返回随机数 operator typename R::result_type() const { return r(); }};int main(){ typedef counting_iterator<rand_int<boost::rand48>, //定义为单遍迭代器 boost::single_pass_traversal_tag, int> RandIter; boost::rand48 r; //一个随机数发生器 rand_int<boost::rand48> r1(r, 0), r2(r, 10); //包装为可递增类型 RandIter first(r1), last(r2); std::vector<int> v; std::copy(first, last, std::back_inserter(v)); assert(v.size() == 10); return 0;}
6.函数输入迭代器
function_input_iterator很类似generator_iterator,同样能够把一个函数或者函数对象适配成输入迭代器,不同的是可以使用一个状态参数设定迭代器的起点和终点(有界)。
function_input_iterator使用模板元编程技术,利用boost.function_types库提取模板参数Function的类型信息,再使用mpl模板元编程技术进行分支决策,在编译期决定从哪个基类继承,它本身并没有实际的功能。
template<class Function,class Input>class function_input_iterator :public mpl::if_< function_types::is_function_pointer<Function>, impl::function_pointer_input_iterator<Function, Input>, typename mpl::if_< function_types::is_function_reference<Function>, impl::function_reference_input_iterator<Function, Input>, impl::function_input_iterator<Function, Input> >::type >::type{ typedef some_define base_type;public: function_input_iterator(Function& f, Input i) :base_type(f, i) {}};
function_input_iterator在名字空间boost::impl里面定义了三个具体实现类,分别对应函数指针、函数引用和函数对象三种情形。
由function_input_iterator的类摘要,可以看出function_input_iterator有两个模板参数,第一个Function与发生器迭代器一样,是一个具有operator()的可调用物,被用来产生迭代器的解引用值,第二个Input要求是一个可递增、可比较、可缺省构造和拷贝构造的类型,也就是支持operator++和operator==。
用起来很像发生器迭代器和计数迭代器的混合体,一方面它把函数或者函数对象适配为一个迭代器,另一方面又能够使用额外的state参数进行技术,在到达终点时自动停止。
同样提供了工厂函数make_function_input_iterator(),不过它有两种重载,分别针对函数指针和函数引用
using namespace std;using namespace boost;rand48 rng; //rand48随机数发生器std::copy( make_function_input_iterator(rng, 0), //从0开始 make_function_input_iterator(rng, 5), //到5结束 ostream_iterator<int>(std::cout, "\n") //标准流输出5个随机数);
对比发生器迭代器的示例代码,这里可以自行控制迭代器的起点和终点,所以可以使用std::copy算法。
状态参数还可以是别的可递增可比较类型:
vector<int> v(10);std::copy( make_function_input_iterator(rng,v.begin()), make_function_input_iterator(rng,v.end()), v.begin() );
function_input_iterator还提供了一个特别的状态类型infinite,它永远不会到达终点:
struct infinite{ infinite& operator++() { return *this; } infinite& operator++(int) { return *this; } bool operator==(infinite&) const { return false; } bool operator==(infinite const&) const { return false; }};
7.函数输出迭代器
function_output_iterator可以把一个单参函数或函数对象适配成一个标准的输出迭代器,它比较特别,没有使用iterator_adaptor或iterator_facade
template<class UnaryFunction>class function_output_iterator{public: typedef std::output_iterator_tag iterator_category; //输出迭代器分类 typedef void value_type; typedef void difference_type; typedef void pointer; typedef void reference; explicit function_output_iterator(); explicit function_output_iterator(const UnaryFunction& f); output_proxy operator*(); //解引用操作 function_output_iterator& operator++();private: UnaryFunction m_f; //函数对象};
解引用操作返回一个代理对象,把赋值操作转化为对函数的调用,因此*iter = t相当于m_f(t)。
用法
使用function_output_iterator配合标准算法std::copy,可以很容易地操作存储在容器中的所有元素,只需要把操作函数适配成迭代器。
示例一段代码定义一个转换ASCII码到十六进制数的函数对象to_hex,它逐个地接受字符,再转换成十六进制数存储在一个外部的vector中。
class to_hex{private: std::vector<unsigned char> &v; //存储十六进制数的容器 int count; //字符计数 char trans(const char c)const //从ASCII码转换到十六进制数 { if (c >= 'a') { return c - 'a' + 10; } else if (c >= 'A') { return c - 'A' + 10; } else { return c - '0'; } }public: to_hex(std::vector<unsigned char> &_v) : v(_v), count(0) {} void operator()(const char c) { static char tmp; if ((count++) % 2 == 0) { tmp = trans(c) * 0x10; } else { tmp += trans(c); v.push_back(tmp); } }};int main(){ char s[] = "1234abcd"; std::vector<unsigned char> v; std::copy(s, s + 8, make_function_output_iterator(to_hex(v))); return 0;}
8.过滤迭代器
filter_iterator可以选择性地迭代序列,筛选出所需的元素,用一个谓词(返回bool值的函数或函数对象)决定选择。
template<class Predicate,class Iterator>class filter_iterator : public iterator_adaptor<...>{public: filter_iterator(); filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); filter_iterator(Iterator x, Iterator end = Iterator()); Predicate predicate() const; Iterator end() const; Iterator const& base() const; reference operator*()const; filter_iterator& operator++();private: Predicate m_pred; //谓词 Iterator m_iter; //迭代器 Iterator m_end; //迭代器终点};
filter_iterator需要两个模板参数,第一个Predicate是过滤条件谓词,用于过滤元素,只有满足条件Predicate(x)==true才会被选择,第二个Iterator是被适配的迭代器类型,应该满足可读和单遍迭代器概念。
用法
示范使用filter_iterator来迭代筛选某个整数区间的质数。
//定义谓词函数bool is_prime(int x){ for (int i = 2; i < x / 2; ++i) { if (x%i == 0) return false; } return true;}int main(){ //假设筛选10~100区间的整数,考虑使用counting_iterator来计数生成这些整数 //所有的偶数都不是质数,所以使用step_iterator跳过所有的偶数 typedef counting_iterator<int> ci_t; ci_t c1(11), c2(101); typedef step_iterator<ci_t> si_t; si_t si1(c1), si2(c2); std::copy( make_filter_iterator(&is_prime, si1, si2), //迭代器起点,si2防止迭代越界 make_filter_iterator(&is_prime, si2, si2), //迭代器终点,si2防止迭代越界 std::ostream_iterator<int>(std::cout, " ") ); return 0;}
9.转换迭代器
transform_iterator把一个单参函数或函数对象应用于迭代的序列,解引用时使用函数来操作序列中的元素,效果与标准库的transform或for_each算法类似。
template<class UnaryFunction, //单参函数对象 class Iterator, //被适配的迭代器 class Reference = use_default, class Value = use_default>class transform_iterator : public iterator_adaptor<...>{public: transform_iterator(); transform_iterator(Iterator const& x, UnaryFunction f); UnaryFunction functor() const; Iterator const& base() const; reference operator*() const; transform_iterator& operator++(); transform_iterator& operator--();private: UnaryFunction m_f;};
transform_iterator需要两个基本的模板参数,UnaryFunction是一个单参的可调用物,第二个Iterator要求满足可读迭代器概念。
transform_iterator的核心是operator*(),它变动了operator*所需的deference()成员函数,解引用原迭代器再调用UnaryFunction操作,相当于m_f(*this->base()),然后返回函数对象的转换结果(返回值)
typedef counting_iterator<int> ci_t; //使用计数迭代器向容器填充10个整数std::vector<int> v;std::copy(ci_t(0), ci_t(10), std::back_inserter(v));auto f = bind(plus<int>(), _1, 5); //使用bind创建函数对象,把整数加5std::copy( make_transform_iterator(v.begin(), f), make_transform_iterator(v.end(), f), std::ostream_iterator<int>(std::cout, " "));
10.索引迭代器
permutation_iterator改变原有序列的索引顺序从而变动迭代顺序。
template< class ElementIterator, class IndexIterator>class permutation_iterator : public iterator_adaptor< permutation_iterator<ElementIterator, IndexIterator> , IndexIterator, typename boost::detail::iterator_traits<ElementIterator>::value_type , use_default, typename boost::detail::iterator_traits<ElementIterator>::reference>{ typedef iterator_adaptor< permutation_iterator<ElementIterator, IndexIterator> , IndexIterator, typename boost::detail::iterator_traits<ElementIterator>::value_type , use_default, typename boost::detail::iterator_traits<ElementIterator>::reference> super_t; friend class iterator_core_access;public: permutation_iterator() : m_elt_iter() {} explicit permutation_iterator(ElementIterator x, IndexIterator y) : super_t(y), m_elt_iter(x) {} template<class OtherElementIterator, class OtherIndexIterator> permutation_iterator( permutation_iterator<OtherElementIterator, OtherIndexIterator> const& r , typename enable_if_convertible<OtherElementIterator, ElementIterator>::type* = 0 , typename enable_if_convertible<OtherIndexIterator, IndexIterator>::type* = 0 ) : super_t(r.base()), m_elt_iter(r.m_elt_iter) {}private: typename super_t::reference dereference() const { return *(m_elt_iter + *this->base()); } ElementIterator m_elt_iter;};
IndexIterator为ElementIterator定义了一个区间,区间大小不一定与原序列相同,可以是一个子区间,区间中元素也可以重复
char s[] = "abcdefg"; //元素序列int idx[] = { 6,0,2,2,4 }; //索引序列std::copy( make_permutation_iterator(s, idx), make_permutation_iterator(s, idx + 5), std::ostream_iterator<char>(std::cout, " "));//g a c c e
11.组合迭代器
zip_iterator使用tuple对多个迭代器”打包“,可以同时移动所有被打包的迭代器,解引用zip_iterator将返回持有多个迭代器解引用结果的tuple。
template<typename IteratorTuple>class zip_iterator : public iterator_facade<...>{public: zip_iterator(); zip_iterator(IteratorTuple iterator_tuple); const IteratorTuple& get_iterator_tuple() const; reference operator*() const; zip_iterator& operator++(); zip_iterator& operator--();private: IteratorTuple m_iterator_tuple;};
zip_iterator只有一个模板参数,它是一个迭代器引用类型的tuple,可以包含多个迭代器,这些迭代器都应该满足可读迭代器概念,zip_iterator的operator*()将返回IteratorTuple中的迭代器各自解引用后的tuple。
用zip_iterator来实现由ASCII码转换到十六进制数的功能
class to_hex2{private: std::vector<unsigned char> &v; char trans(const char c)const //从ASCII码转换到十六进制数 { if (c >= 'a') { return c - 'a' + 10; } else if (c >= 'A') { return c - 'A' + 10; } else { return c - '0'; } }public: to_hex2(std::vector<unsigned char> &_v) :v(_v) {} typedef boost::tuple<const char&, const char&> Tuple; void operator()(Tuple const& t)const { static char tmp; tmp = trans(get<0>(t)) * 0x10; tmp += trans(get<1>(t)); v.push_back(tmp); }};int main(){ char s[] = "1234aBcD"; //base16编码字符串 std::vector<unsigned char> v; typedef step_iterator<const char*> si_t; std::for_each( make_zip_iterator(boost::make_tuple(si_t(s), si_t(s + 1))), make_zip_iterator(boost::make_tuple(si_t(s + 8), si_t(s + 9))), to_hex2(v) ); assert(v.size() == 4); return 0;}
- Boost库迭代器
- Boost
- boost
- boost
- Boost
- boost
- boost
- Boost
- Boost
- Boost
- boost
- boost
- Boost
- boost
- boost
- boost
- boost
- boost
- eclipse怎么全选jar包
- 多线程之初步:隔一秒打印一个,输入s停止
- Java JVM 2: 锁优化
- 应用上悬浮的快速启动菜单
- 107. Binary Tree Level Order Traversal II
- Boost库迭代器
- Kafka 几个实现细节
- TensorFlow初学(一)
- win7系统thumbs.db文件怎么彻底删除
- jsp中iframe在子页面和父页面之间传值
- oracle各个版本下载(官网要登录,复制链接迅雷下载)
- 回调函数的C++实现
- hibernate入门
- Spyder安装和使用和安装PyQt4(单独为了装python的ide)