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;}
原创粉丝点击