Boost C++ 库

……世界上最受推崇且设计最专业的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu,《C++ 编码规范

Zip 迭代器 - Boost C++ 函数库

Zip 迭代器

作者 David Abrahams, Thomas Becker
联系方式 dave@boost-consulting.com, thomas@styleadvisor.com
组织 Boost Consulting, Zephyr Associates, Inc.
日期 2006-09-11
版权 版权所有 David Abrahams 和 Thomas Becker 2003。
摘要 zip_iterator(压缩迭代器)提供了同时对多个受控序列进行并行迭代的能力。zip_iterator 是由一个迭代器元组构造而成的。移动 zip_iterator 会并行移动所有包含的迭代器。对 zip_iterator 进行解引用操作,会返回一个包含各个迭代器解引用结果的元组。

zip_iterator概要

template<typename IteratorTuple>
class zip_iterator
{

public:
  typedef /* see below */ reference;
  typedef reference value_type;
  typedef value_type* pointer;
  typedef /* see below */ difference_type;
  typedef /* see below */ iterator_category;

  zip_iterator();
  zip_iterator(IteratorTuple iterator_tuple);

  template<typename OtherIteratorTuple>
  zip_iterator(
        const zip_iterator<OtherIteratorTuple>& other
      , typename enable_if_convertible<
              OtherIteratorTuple
            , IteratorTuple>::type* = 0     // exposition only
  );

  const IteratorTuple& get_iterator_tuple() const;

private:
  IteratorTuple m_iterator_tuple;     // exposition only
};

template<typename IteratorTuple>
zip_iterator<IteratorTuple>
make_zip_iterator(IteratorTuple t);

reference成员zip_iterator是其元组的类型,该元组由迭代器类型中的引用类型组成IteratorTuple参数。

difference_type成员zip_iteratordifference_type是 IteratorTuple 中第一个迭代器类型的IteratorTuple参数。

iterator_category成员zip_iterator可转换为迭代器类型中遍历类别的最小值,该类型位于IteratorTuple参数中。例如,如果zip_iterator仅持有 vector 迭代器,则iterator_category可转换为boost::random_access_traversal_tag。如果你增加了一个 list 迭代器,那么iterator_category将可以转换为boost::bidirectional_traversal_tag,但不再能转换为boost::random_access_traversal_tag.

zip_iteratorrequirements

参数中的所有迭代器类型都IteratorTuple都必须是 Readable Iterator。

zip_iterator模型

生成的zip_iterator模拟了可读迭代器(Readable Iterator)。

事实上zip_iterator仅模拟了可读迭代器,这并不妨碍你修改各个迭代器所指向的值。由 zip_iterator 返回的元组是根据各个迭代器的引用类型而非值类型构造的。例如,如果zip_iteratoroperator*zip_it其第一个成员迭代器是一个zip_iteratorstd::vector<double>::iterator,那么下面这行代码将修改zip_it其第一个成员迭代器是一个当前第一个成员迭代器所指向的值。

zip_it->get<0>() = 42.0;

考虑通过获取参数中每个单独迭代器类型所模拟的最精炼的标准遍历概念而得到的标准遍历概念集。IteratorTuplezip_iteratorzip_iterator模拟了该集合中最不精炼的标准遍历概念。

zip_iterator<IteratorTuple1>zip_iterator<IteratorTuple2>当且仅当IteratorTuple1IteratorTuple2.

zip_iterator操作

除了参数所模拟的概念所要求的操作之外,zip_iterator, zip_iterator还提供了以下操作。

zip_iterator();

返回的一个实例zip_iterator带有m_iterator_tuple默认构造。

zip_iterator(IteratorTuple iterator_tuple);

返回的一个实例zip_iterator带有m_iterator_tuple初始化为iterator_tuple.
template<typename OtherIteratorTuple>
zip_iterator(
      const zip_iterator<OtherIteratorTuple>& other
    , typename enable_if_convertible<
            OtherIteratorTuple
          , IteratorTuple>::type* = 0     // exposition only
);
返回的一个实例zip_iterator它是other.
要求OtherIteratorTuple隐式转换为IteratorTuple.

的副本。const IteratorTuple& get_iterator_tuple() const;

返回m_iterator_tuple

reference operator*() const;

返回返回一个由所有迭代器解引用结果组成的元组。m_iterator_tuple.

zip_iterator& operator++();

效果递增每个迭代器在m_iterator_tuple.
返回*this

zip_iterator& operator--();

效果递减每个迭代器在m_iterator_tuple.
返回*this
template<typename IteratorTuple>
zip_iterator<IteratorTuple>
make_zip_iterator(IteratorTuple t);
返回的一个实例zip_iterator<IteratorTuple>带有m_iterator_tuple初始化为t.
template<typename IteratorTuple>
zip_iterator<IteratorTuple>
make_zip_iterator(IteratorTuple t);
返回的一个实例zip_iterator<IteratorTuple>带有m_iterator_tuple初始化为t.

示例

zip_iterator 有两个主要应用场景。zip_iterator第一个与运行时效率有关:如果拥有多个等长的受控序列需要以某种方式处理(例如使用for_each算法),那么执行一次并行迭代比执行多次单独迭代效率更高。例如,假设vect_of_doublesandvect_of_ints是两个等长的 vector,分别包含 double 和 int,并考虑以下两次迭代:

std::vector<double>::const_iterator beg1 = vect_of_doubles.begin();
std::vector<double>::const_iterator end1 = vect_of_doubles.end();
std::vector<int>::const_iterator beg2 = vect_of_ints.begin();
std::vector<int>::const_iterator end2 = vect_of_ints.end();

std::for_each(beg1, end1, func_0());
std::for_each(beg2, end2, func_1());

这两次迭代现在可以替换为一次迭代,如下所示

std::for_each(
  boost::make_zip_iterator(
    boost::make_tuple(beg1, beg2)
    ),
  boost::make_zip_iterator(
    boost::make_tuple(end1, end2)
    ),
  zip_func()
  );

一个非泛型的zip_func实现可能如下所示:

struct zip_func :
  public std::unary_function<const boost::tuple<const double&, const int&>&, void>
{
  void operator()(const boost::tuple<const double&, const int&>& t) const
  {
    m_f0(t.get<0>());
    m_f1(t.get<1>());
  }

private:
  func_0 m_f0;
  func_1 m_f1;
};

第二个重要应用是zip_iterator作为构建组合迭代器(combining iterator)的组件。组合迭代器是一种可以对多个受控序列进行并行迭代,并在解引用时返回将函数对象应用于序列相应位置的值的结果的迭代器。现在可以通过结合使用zip_iteratorzip_iteratortransform_iterator.

与 transform_iterator 来实现这一点。例如,假设你有两个 double 类型的 vector,即vect_1andvect_2,你需要向客户端公开一个包含vect_1andvect_2vect_1 和 vect_2 元素乘积的受控序列。与其将这些乘积放入第三个 vector 中,不如使用一个在遍历时即时计算乘积的组合迭代器。让我们假设tuple_multiplies是一个工作方式类似于std::multiplies的函数对象,区别在于它接受封装在元组中的两个参数。那么下面定义的两个迭代器it_beginandit_end界定了一个包含 vect_1 和 vect_2 元素乘积的受控序列。vect_1andvect_2:

typedef boost::tuple<
  std::vector<double>::const_iterator,
  std::vector<double>::const_iterator
  > the_iterator_tuple;

typedef boost::zip_iterator<
  the_iterator_tuple
  > the_zip_iterator;

typedef boost::transform_iterator<
  tuple_multiplies<double>,
  the_zip_iterator
  > the_transform_iterator;

the_transform_iterator it_begin(
  the_zip_iterator(
    the_iterator_tuple(
      vect_1.begin(),
      vect_2.begin()
      )
    ),
  tuple_multiplies<double>()
  );

the_transform_iterator it_end(
  the_zip_iterator(
    the_iterator_tuple(
      vect_1.end(),
      vect_2.end()
      )
    ),
  tuple_multiplies<double>()
  );