在矢量上的成对迭代

时间:2012-03-19 04:25:56

标签: c++ stl vector iterator containers

问题概要

给定std::vector<T>,我如何创建一个公开std::vector<std::pair<T, T>>接口的视图,其中每对由底层向量中的两个连续元素组成?

详细

目标是在同一存储上创建多个容器抽象,即std::vector<T>T类型是某种受歧视的联盟,{la Boost Variant。给出了存储要求,否则我只会使用std::vector<std::pair<T, T>>。我想要支持的存储视图是集合(唯一元素)和表格(关联数组,唯一键)。虽然前者通过确保设置唯一性属性是直截了当的,但后者需要处理键和值。

为了支持std::vector<T>上的关联数组语义,我目前认为最好的方法是创建一个std::vector<std::pair<T, T>>形式的视图,并且这个视图允许我使用STL算法来保持所需的属性。这听起来像是一个好策略吗?还有其他想法吗?

相关

如果我有一个遍历每个偶数元素的迭代器 i 和遍历每个奇数元素的迭代器 j ,那么我会想到Boost的zip iterator,将启用(i,j)对中的迭代。但我的用例略有不同,因为我没有两个独立的容器。

2 个答案:

答案 0 :(得分:2)

似乎Boost的iterator_facade确实是我想要的。这是一个玩具示例(边缘粗糙):

#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/iterator/iterator_facade.hpp>

template <typename Value>
class pair_iterator
  : public boost::iterator_facade<
        pair_iterator<Value>
      , Value
      , boost::random_access_traversal_tag
      , std::pair<Value&, Value&>
      , typename std::vector<Value>::difference_type
    >
{
public:
    typedef std::vector<Value> vector_type;
    typedef typename vector_type::difference_type difference_type;
    typedef typename vector_type::iterator iterator;

    pair_iterator()
        : i_(0)
    {
    }

    explicit pair_iterator(iterator i)
      : i_(i)
    {
    }

private:
    friend class boost::iterator_core_access;

    bool equal(pair_iterator<Value> const& other) const
    {
        return i_ == other.i_;
    }

    void increment()
    {
        ++i_;
        ++i_;
    }

    std::pair<Value&, Value&> dereference() const
    {
        return { std::ref(*i_), std::ref(*(i_ + 1)) };
    }

    void advance(difference_type n)
    {
        i_ += n << 1;
    }

    difference_type distance_to(pair_iterator<Value> const& other) const
    {
        return other.i_ - i_;
    }

    iterator i_;
};

int main()
{
    typedef pair_iterator<int> int_map_iterator;
    std::vector<int> v{2, 20, 3, 30, 5, 50, 7, 70};
    int_map_iterator first(v.begin());
    int_map_iterator last(v.end());

    std::for_each(first + 1, last,
                  [](std::pair<int&, int&> p)
                  {
                      std::cout
                          << p.first << " -> "
                          << p.second << std::endl;
                  });

    return 0;
}

输出结果为:

3 -> 30
5 -> 50
7 -> 70

问题

  • 此示例尚未解决从iteratorconst_iterator的转换问题。
  • 迭代器仅在基础向量具有偶数大小且需要更保守的dereference()实现时才有效。

答案 1 :(得分:0)

首先要注意的是,您将无法公开std::pair<T const, T>&作为修改对象的方法。然而,可能足够接近的是std::pair<T const, T&>因为你只能改变第二部分。

这样看起来你需要

  1. 迭代器类型,它跳过所有其他值,用于迭代键(具有偶数索引的元素)和值(具有奇数索引的元素)。
  2. 类似于“zip iterator”的东西,它接受两个迭代器并公开从它们获得的std::pair<T const, T&>