从迭代器开始遍历原始序列的已过滤范围(循环)遍历

时间:2020-04-02 18:42:14

标签: c++ range-v3

假设您有一个容器,并对该容器的某些元素进行了迭代。要求是循环使用该迭代器,但要使用过滤器。现在,在序列上创建过滤后的(圆形)视图是微不足道的,但是当所有对象都是原始对象的迭代器时,如何启动遍历?我正在考虑串联两个范围,例如:

#include <iostream>

#include <range/v3/all.hpp>
using namespace ranges;

int main () {
    std::vector< int > xs{ -4, 1, 3, -4, 2, -3, 6, 7, 8, -9, -10 };

    auto iter = xs.begin ();
    std::advance (iter, 8);

    std::cout << *iter << std::endl;

    auto lhs = make_subrange (iter, xs.end ());
    auto rhs = make_subrange (xs.begin (), iter);

    auto is_pos = [](auto x) { return x >= 0; };
    auto rng = views::cycle (views::concat (lhs, rhs) | views::filter (is_pos));

    auto next = ++rng.begin ();
    std::cout << *next << std::endl;

    return 0;
}

有没有更简单的方法?

1 个答案:

答案 0 :(得分:1)

是的,您可以简单地iter之前的元素drop而不是在iter处串联两个子范围。

因此,这段代码

auto lhs = make_subrange (iter, xs.end ());
auto rhs = make_subrange (xs.begin (), iter);

auto rng = views::cycle (views::concat (lhs, rhs) | views::filter (is_pos));

成为

auto rng = xs | views::cycle
              | views::drop(distance(xs.begin(), iter))
              | views::filter(is_pos);

请注意,尽管此解决方案更简单,但它会遍历所有未过滤的元素,并多次应用过滤谓词。您的解决方案可能比这更有效。