简体   繁体   English

随后在多个std容器上迭代

[英]iterator over multiple std containers subsequently

I have the following class (which obviously does not yet work as intended): 我有以下课程(显然还没有按预期工作):

class A
{
private:
    std::vector<int> firstVector, secondVector;
public:
    std::vector<int>::iterator begin(){
        return firstVector.begin();
    }
    std::vector<int>::iterator end(){
        return secondVector.end();
    }
};

How can I define an iterator which will go over the two member containers subsequently, eg after firstVector.end()-1 secondVector.begin() is returned and going all the way to secondVector.end() ? 我如何定义一个迭代器,它将随后遍历两个成员容器,例如在firstVector.end()-1返回firstVector.end()-1 secondVector.begin()并一直到secondVector.end()

Basically you need to define some custom iterator that internally checks for the end of the first range, then goes on to the next one. 基本上你需要定义一些自定义迭代器,它在内部检查第一个范围的结束,然后继续下一个范围。

However, this sort of stuff occurs a lot. 然而,这种事情发生了很多。 Eventually you'd ask why an iterator for two vectors, why an iterator for two vectors , why a sequence of the same container type, and so on. 最终,你会问,为什么一个迭代的两个向量,为什么两个向量的迭代器,为什么同样的容器类型的序列,依此类推。 Nir Tzachar & I have written a C++ port of Python itertools that does this sort of common stuff. Nir Tzachar和我编写了一个Python itertoolsC ++端口来完成这种常见的事情。 In this case, you'd just use 在这种情况下,你只需使用

chain(firstVector, secondVector)

It can be downloaded from this bitbucket repo . 它可以从这个bitbucket repo下载。

Nothing to stop you from rolling your own. 没有什么可以阻止你自己滚动。 Can even make it random access! 甚至可以让它随机访问!

struct chain_iterator 
    : std::iterator<std::random_access_iterator_tag, int>
{
    using it = std::vector<int>::iterator;

    std::pair<it, it> v1, v2;
    bool first;
    it cur;
};

We keep the initial iterator pairs so that we can do random access correctly. 我们保留初始迭代器对,以便我们可以正确地进行随机访问。

Incrementing is what you'd expect: 增量是你所期望的:

chain_iterator& operator++() {
    ++cur;
    if (first && cur == v1.second) {
        first = false;
        cur = v2.first;
    }
    return *this;
}

Dereference is trivial: 取消引用是微不足道的:

int& operator*() { return *cur; }

Advance has to do some extra checking: Advance需要做一些额外的检查:

chain_iterator& operator+=(size_t n) {
    if (!first) {
        // trivial case
        cur += n;
    }
    else {
        size_t d = v1.second - cur;
        if (d < n) {
            cur += n;
        }
        else {
            first = false;
            cur = v2.first + (d - n);
        }
    }
    return *this;
}

I'll leave the rest of the operations as an exercise. 我将把剩下的操作留作练习。

You could write your own function to do the incrementing: 您可以编写自己的函数来进行递增:

std::vector<int>::iterator& inc(std::vector<int>::iterator& it) {
    ++it;
    if (it == firstVector.end())
        it = secondVector.begin();
    return it;
}

This is also a good indication to others that the increment doesn't happen normally. 这也是对其他人的良好指示,即增量不会正常发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM