You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用C++ ranges/std::views实现输入迭代器的分段消费?

可以用std::ranges/std::views实现相同功能

原代码通过手动操作输入迭代器完成了分段消费的逻辑,用C++20引入的std::ranges和std::views可以更简洁、声明式地实现完全一致的行为,同时保留输入迭代器的单次遍历特性。

对应实现代码

#include <ranges>
#include <iostream>
#include <numeric>

void test(std::input_iterator auto it) {
    namespace rv = std::ranges::views;
    namespace rg = std::ranges;

    // 将输入迭代器包装为标准输入范围
    auto rng = rv::subrange(it, std::default_sentinel);

    // 跳过所有小于1的元素,对应原代码的while循环
    auto after_drop = rng | rv::drop_while([](int x) { return x < 1; });

    // 提取第一个元素作为计数n,同时获取后续元素的范围
    int n = *rg::begin(after_drop);
    auto rest_elements = after_drop | rv::drop(1);

    // 取n个元素,每个加1后求和,对应原代码的累加循环
    int sum = rg::fold_left(
        rest_elements | rv::take(n) | rv::transform([](int x) { return x + 1; }),
        0,
        std::plus<>()
    );

    // 跳过前n个元素,将剩余元素除以2,取非零值直到遇到0,最后求积
    int prd = rg::fold_left(
        rest_elements | rv::drop(n) | rv::transform([](int x) { return x / 2; }) | rv::take_while([](int x) { return x != 0; }),
        1,
        std::multiplies<>()
    );

    std::cout << sum << ' ' << prd << '\n';
}

int main() {
    test(std::begin({0, 0, 0, 3, 400, 30, 2, 4, 6, 0}));
}

代码与原逻辑的对应关系

  • rv::drop_while 直接替代原代码中跳过小于1元素的while循环;
  • 通过rg::begin(after_drop)获取第一个元素作为n,rv::drop(1)得到后续元素范围,对应原代码中取*it并递增迭代器的操作;
  • rv::take(n) | rv::transform(...) 配合rg::fold_left完成求和逻辑,和原代码中循环n次累加的结果完全一致;
  • rv::drop(n)跳过已处理的n个元素后,用rv::transform执行除以2的操作,再通过rv::take_while过滤到0为止,最后用rg::fold_left求积,对应原代码中直到*it/2为0时停止的循环。

运行这段代码会得到和原代码完全相同的输出:435 6。

内容的提问来源于stack exchange,提问作者Abyx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 15:00:38