关于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
相关产品推荐
相关产品推荐

