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

如何用C++协程实现views::concat?求更优实现方案

实现无依赖的cppcoro版views::concat

Eric Niebler曾说:“协程让自定义范围变得轻而易举”,受这句话启发,我尝试用C协程实现还未纳入C23标准的views::concat。由于当前编译器不支持std::generator,我选择使用cppcoro库来实现。

踩过的坑

  • 最初尝试用折叠表达式展开lambda,但返回的generator对象被直接丢弃,无法正确传递元素
  • 尝试co_yield rngs...的写法,编译器直接报错,这种语法本身不符合协程的yield规则

当前实现的不足

后来通过生成器lambda、std::array存储各个子生成器,再结合views::join实现了拼接功能,但该方案依赖std::array和views::join,不仅不够简洁,还带来了额外的容器存储开销。

优化后的实现

改用递归展开参数包的协程写法,完全摆脱对额外容器和视图的依赖:

#include <cppcoro/generator.hpp>
#include <type_traits>

// 处理单个或多个输入范围的核心实现
template<typename FirstRange, typename... RestRanges>
cppcoro::generator<std::decay_t<typename FirstRange::value_type>> concat(FirstRange&& first, RestRanges&&... rest)
{
    // 逐个yield第一个范围的所有元素
    for (auto&& elem : std::forward<FirstRange>(first))
    {
        co_yield std::forward<decltype(elem)>(elem);
    }

    // 递归处理剩余的范围
    if constexpr (sizeof...(rest) > 0)
    {
        auto rest_gen = concat(std::forward<RestRanges>(rest)...);
        for (auto&& elem : rest_gen)
        {
            co_yield std::forward<decltype(elem)>(elem);
        }
    }
}

// 空参数重载(可选,避免无参数调用时编译错误)
cppcoro::generator<void> concat()
{
    co_return;
}

实现优势

  • 无额外依赖:不需要std::array或views::join,仅依赖cppcoro库
  • 惰性求值:元素按需生成,和标准库视图的行为一致,避免不必要的内存开销
  • 完美转发:支持左值、右值等各种可迭代范围,保证元素和范围的生命周期正确
  • 简洁高效:递归逻辑清晰,直接逐个转发元素,性能更接近原生迭代

内容的提问来源于stack exchange,提问作者康桓瑋

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 20:22:22