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

为何新版编译器允许将非viewable_range的右值范围传给部分范围适配器?

为什么新版C++编译器允许右值范围传给部分范围适配器?

核心原因是C++标准通过P2415R2提案扩展了范围适配器的能力,让它们可以接受可移动的右值范围,并自动将其包装为std::ranges::owning_view,从而满足viewable_range的要求。

1. 原C++20标准的限制

最初的C++20标准规定,范围适配器的第一个参数必须是viewable_range,即:

  • 要么是view(轻量、可复制的范围类型);
  • 要么是borrowed_range(迭代器不会悬空的范围,比如左值容器)。

右值容器(如std::vector{1,2,3})既不是view,也不属于borrowed_range,所以旧版编译器会拒绝将其传给范围适配器。

2. P2415R2带来的变化

为了提升易用性,P2415R2给范围适配器新增了重载:当传入可移动的右值范围时,适配器会自动把它包装成owning_view——这是一种持有范围所有权的view,自然符合viewable_range的定义。clang 16.0.0、gcc 12.0及以上版本实现了这个提案,因此允许这类代码编译通过。

3. 你的测试案例解析

  • std::views::drop(std::vector{1,2,3,4,5}, 2):新版编译器将右值vector包装为owning_view后再应用drop,最终生成合法的view;旧版编译器未实现该提案,因此报错。
  • 修正后的std::views::transform(...):同样,新版编译器自动处理右值vector,包装为owning_view后适配transform,所以编译通过;你最初的笔误代码(传2而非lambda)本身不符合transform的参数要求,因此无论编译器版本都无法编译。

4. 本质没有打破规则

这类代码并没有违反viewable_range的定义——适配器实际接收的是包装后的owning_view(属于view),仍然满足viewable_range的要求。只要编译器实现了P2415R2,大部分标准范围适配器(如filter、take等)都支持这种右值范围的自动转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 00:42:13