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

关于Range-v3中actions::join与transform的管道语法疑问

Range-v3 Actions 相关疑问:join与transform的管道语法困惑

本人大量使用Range-v3,但主要用视图(views)和算法,较少使用动作(actions)。针对ranges::actions::join,存在如下疑问:

auto strs{std::vector{"one"s, "twoooooooooooooooooooooooooo"s, "three"s}};
           
auto str1 = join(strs) | to<std::string>;             // join接受左值范围                                                                              
auto str2 = std::move(strs) | join | to<std::string>; // join不接受左值范围

移除最后一行的std::move会导致action.hpp中的约束检查失败:

#ifndef RANGES_WORKAROUND_CLANG_43400
            template<typename Rng, typename ActionFn>   // ******************************
            friend constexpr auto                       // ******************************
            operator|(Rng &,                            // ********* READ THIS **********
                      action_closure<ActionFn> const &) // ****** IF YOUR COMPILE *******
                -> CPP_broken_friend_ret(Rng)(          // ******** BREAKS HERE *********
                    requires range<Rng>) = delete;      // ******************************
            // **************************************************************************
            // *    When piping a range into an action, the range must be moved in.     *
            // **************************************************************************
#endif // RANGES_WORKAROUND_CLANG_43400

但结合join的实现来看,它会返回新容器ret,且未对rng或其元素执行std::move,为何管道语法要求传入被move的范围?若该要求合理,为何约束是在|层面而非join层面?


此外,针对ranges::actions::transform存在对称疑问:该动作会原地转换输入范围,因此管道语法需要std::move:

constexpr auto twice = [](auto s){ return s + s; };
strs = std::move(strs) | transform(twice); // std::move是必需的

但为何可以直接写:

strs = transform(strs, twice);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:17:08