Boost库迭代器

《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创建函数对象,把整数加5

std::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;
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值