用C++封装std::iterator

4

我需要包装一个向量迭代器,但不想从头开始重写它。而且我无法对其进行子类化,因为向量迭代器似乎不是跨平台的。至少gnu和ibm的迭代器看起来不同。

我想要做的是:

class MyContainer {
    vector<double> data;
    vector<int> indices;

    iterator
    begin()
    { return my_iterator(data, indices.begin()); }

    iterator
    end()
    { return my_iterator(data, indices.end()); }
}

MyContainer  cont;

indices向量包含数据向量内的整数位置。数据应该比索引要大得多。

因此,我需要一个迭代器,可以像普通向量迭代器一样沿任何方向遍历索引,但唯一的例外是:当要访问值时,它必须返回数据向量的值。例如:

for(MyContainer::iterator it = cont.begin(); it != cont.end(); it++) {
    cout << *it << endl; // values of data should appear here
}

基本上它应该看起来像标准世界中的普通集合。您可以按任何方向迭代它,可以对其进行排序、运行唯一性查找、find_if等操作... 有没有简单的解决方案?

1
如果我理解正确,你实际上有一组双精度浮点数的向量,而索引向量是没有意义的。或者也许我错了,我并没有清楚地了解你真正想要实现什么。 - wkl
我有两个向量。其中一个包含大数据集(10k元素)。索引将指向数据集中的子集。就像这样:indices = {1, 2, 5, 1000}; 我想通过容器进行迭代,就好像我是在indices向量上进行迭代一样,但返回的值必须从数据向量中获取。 - novak Li
@birryee,我的猜测是indices向量中的值实际上是data向量中的索引,并且他想输出迭代器引用的当前索引处data向量的值。 - Moo-Juice
3个回答

6

有一个很棒的Boost库可以定义自定义迭代器。您需要提供一个带有几个方法的类:

i.dereference()  Access the value referred to
i.equal(j)       Compare for equality with j
i.increment()    Advance by one position
i.decrement()    Retreat by one position
i.advance(n)     Advance by n positions
i.distance_to(j) Measure the distance to j

然后你可以从iterator_facade中获取其余部分。

祝好运!


4

类似,但是permutation_iterator会对一系列连续的索引进行排列。OP想要更像是一个combination_iterator(如果有的话),这样就可以跳过一些索引。 - outis
@outis: 我不相信索引的范围必须是连续的。看一下页面底部的例子。“indices”是一个list<int>,在这个例子中恰好填充了连续的数字,但它也可以包含其他任何内容。 - Éric Malenfant
@outis:我在codepad上创建了一个非连续索引的示例。请查看我的回答中的链接。 - Éric Malenfant
@Éric:你说得对。我是根据介绍中的文本来判断的。 - outis
是的,非常感谢。permutation_iterator 正是我所需要的。 - novak Li

2

标准C++库中没有相关内容,但是你可以使用boost::iterator_adapter来实现你的需求。初步检查表明,你需要重写iterator_adapter::dereferenceiterator_adapter::equal

template <typename _Scalar=double,
          typename _Idx=int, 
          typename _Seq=std::vector<_Scalar>, 
          typename _IdxVector=std::vector<_Idx> >
class SelIter 
    : public boost::iterator_adaptor< SelIter<_Scalar, _Idx>, 
                                      typename _IdxVector::iterator, _Scalar > 
{
public:
    typedef boost::iterator_adaptor< SelIter, typename _IdxVector::iterator, _Scalar > Base;

    SelIter(_Seq& scalars, _IdxVector& idxs);
    SelIter(_Seq& scalars, typename _IdxVector::iterator pi);

    typename Base::reference dereference() const;
    bool equal(const SelIter& x) const;
private:
    // ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接