范围库 (C++20)
范围库是对迭代器和泛型算法库的一个扩展,使得迭代器和算法可以通过组合变得更强大,并且减少错误。
范围库创造并操作范围视图,它们是间接表示可遍历的序列(范围)的轻量对象。 范围是对以下内容的抽象:
-
[begin,end)– 迭代器对,例如,范围可以从容器隐式转换而得。所有接受迭代器对的算法现在都有接受范围的重载(例如 ranges::sort) - begin
+[0,size)– 计数的序列,例如 views::counted 返回的范围 -
[begin,谓词)– 按条件终止的序列,例如 views::take_while 返回的范围 -
[begin,..)– 无界序列,例如 views::iota 返回的范围
范围库包括急切应用到范围上的范围算法,和惰性地应用到视图上的范围适配器。适配器可以组合成管线,它们的动作在视图迭代时实际发生。
| 在标头 <ranges> 定义
|
||
| namespace std { namespace views = ranges::views; |
(C++20 起) | |
提供命名空间别名 std::views,作为 std::ranges::views 的缩写。
| 在命名空间
std::ranges 定义 | ||
范围访问 | ||
| 在标头
<ranges> 定义 | ||
| 在标头
<iterator> 定义 | ||
| (C++20) |
返回指向范围起始的迭代器 (定制点对象) | |
| (C++20) |
返回指示范围结尾的哨位 (定制点对象) | |
| (C++20) |
返回指向只读范围起始的迭代器 (定制点对象) | |
| (C++20) |
返回指示只读范围结尾的哨位 (定制点对象) | |
| (C++20) |
返回指向范围的逆向迭代器 (定制点对象) | |
| (C++20) |
返回指向范围的逆向尾迭代器 (定制点对象) | |
| (C++20) |
返回指向只读范围的逆向迭代器 (定制点对象) | |
| (C++20) |
返回指向只读范围的逆向尾迭代器 (定制点对象) | |
| (C++20) |
返回等于范围大小的整数 (定制点对象) | |
| (C++20) |
返回等于范围大小的有符号整数 (定制点对象) | |
| (C++20) |
检查范围是否为空 (定制点对象) | |
| (C++20) |
获得指向连续范围的起始的指针 (定制点对象) | |
| (C++20) |
获得指向只读连续范围的起始的指针 (定制点对象) | |
范围原语 | ||
| 在标头
<ranges> 定义 | ||
| (C++20)(C++23)(C++20)(C++23)(C++20)(C++20)(C++20)(C++20)(C++23)(C++20)(C++20) |
获取关联的范围类型 (别名模板) | |
悬垂迭代器处理 | ||
| 在标头
<ranges> 定义 | ||
| (C++20) |
占位类型,指示不应返回迭代器或子范围,因为它可能悬垂 (类) | |
获得塑造 borrowed_range 的迭代器类型或子范围类型 (别名模板) | ||
范围概念 | ||
| 在标头
<ranges> 定义 | ||
| (C++20) |
指定类型为范围,即它同时提供 begin 迭代器和 end 哨位 (概念) | |
| (C++20) |
指定类型为 range 而且能安全返回从该类型表达式获得的迭代器而无悬垂之虞 (概念) | |
| (C++20) |
指定类型为可在常数时间内知晓大小的范围 (概念) | |
| (C++20) |
指定范围为视图,即它拥有常数时间的复制/移动/赋值 (概念) | |
| (C++20) |
指定范围的迭代器类型满足 input_iterator (概念) | |
| (C++20) |
指定范围的迭代器类型满足 output_iterator (概念) | |
| (C++20) |
指定范围的迭代器类型满足 forward_iterator (概念) | |
| (C++20) |
指定范围的迭代器类型满足 bidirectional_iterator (概念) | |
| (C++20) |
指定范围的迭代器类型满足 random_access_iterator (概念) | |
| (C++20) |
指定范围的迭代器类型满足 contiguous_iterator (概念) | |
| (C++20) |
指定范围拥有相同的迭代器和哨位类型 (概念) | |
| (C++20) |
指定针对 range 的要求,令其可安全转换为 view (概念) | |
| (C++23) |
指定范围的所有元素只读 (概念) | |
范围转换 | ||
| 在标头
<ranges> 定义 | ||
| (C++23) |
从输入范围构造一个新的非视图对象 (函数模板) | |
视图 | ||
| 在标头
<ranges> 定义 | ||
| (C++20) |
用于定义 view 的辅助类模板,使用奇特重现模板模式 (类模板) | |
| (C++20) |
将迭代器/哨位对结合为一个 view (类模板) | |
[编辑] 范围工厂
| 在标头
<ranges> 定义 | |
| 在命名空间
std::ranges 定义 | |
无元素的空 view (类模板) (变量模板) | |
含有具有指定值的单个元素的 view (类模板) (定制点对象) | |
| (C++20) |
由通过重复对某个初值自增所生成的序列组成的 view (类模板) (定制点对象) |
由在关联的输入流上相继应用 operator>> 获得的元素组成的 view (类模板) (定制点对象) | |
由重复产出同一值生成的序列组成的 view (类模板) (定制点对象) | |
[编辑] 范围适配器
| 在标头
<ranges> 定义 | |
| 在命名空间
std::ranges 定义 | |
| 用于定义范围适配器闭包对象的辅助基类模板 (类模板) | |
| (C++20) |
包含 range 的所有元素的 view (别名模板) (范围适配器对象) |
| (C++20) |
某个其他 range 的元素的 view (类模板) |
| (C++20) |
拥有某 range 的独占所有权的 view (类模板) |
由 range 中满足某个谓词的元素构成的 view (类模板) (范围适配器对象) | |
对序列的每个元素应用某个变换函数的 view (类模板) (范围适配器对象) | |
| (C++20) |
由另一 view 的前 N 个元素组成的 view (类模板) (范围适配器对象) |
由另一 view 的到首个谓词返回 false 为止的起始元素组成的 view (类模板) (范围适配器对象) | |
| (C++20) |
由另一 view 跳过前 N 个元素组成的 view (类模板) (范围适配器对象) |
由另一 view 跳过元素的起始序列,直至首个使谓词返回 false 的元素组成的 view (类模板) (范围适配器对象) | |
| (C++20) |
由拉平 range 组成的 view 所获得的序列构成的 view (类模板) (范围适配器对象) |
用某个分隔符切割另一 view 所获得的子范围的 view (类模板) (范围适配器对象) | |
用某个分隔符切割另一 view 所获得的子范围的 view (类模板) (范围适配器对象) | |
| (C++20) |
从迭代器和计数创建子范围 (定制点对象) |
转换 view 为 common_range (类模板) (范围适配器对象) | |
以逆序迭代另一双向视图上的元素的 view (类模板) (范围适配器对象) | |
选取 tuple-like 值组成的 view 和数值 N,产生每个元组的第 N 个元素组成的 view (类模板) (范围适配器对象) | |
| (C++20) |
选取对偶式值组成的 view 并产生每个对偶的第一元素的 view (类模板) (范围适配器对象) |
接受一个由对偶式值组成的 view 并产生每个对偶的第二元素组成的 view (类模板) (范围适配器对象) | |
将被适配视图的各元素映射为元素位置和其值组成的元组的 view (类模板) (范围适配器对象) | |
| (C++23) |
到被适配视图的对应元素的引用元组组成的 view (类模板) (定制点对象) |
由应用变换函数到被适配视图的对应元素的结果的元组组成的 view (类模板) (定制点对象) | |
由到被适配视图的相邻元素的引用的元组组成的 view (类模板) (范围适配器对象) | |
由应用变换函数到被适配视图的相邻元素的结果的元组组成的 view (类模板) (范围适配器对象) | |
由拉平范围组成的视图并以分隔符间隔所获得的序列构成的 view (类模板) (范围适配器对象) | |
第 M 个元素是另一 view 从第 M 到第 (M + N - 1) 个元素的 view 构成的 view (类模板) (范围适配器对象) | |
另一个视图元素的 N 大小不重叠的连续块组成的 view 的范围 (类模板) (范围适配器对象) | |
在给定谓词返回 false 的每一对相邻元素处,将 view 切分为子范围 (类模板) (范围适配器对象) | |
转换 view 为 constant_range (类模板) (范围适配器对象) | |
由将序列所有元素转换为右值组成的 view (类模板) (范围适配器对象) | |
由另一 view 的元素每次前进 N 步所获得的 view (类模板) (范围适配器对象) | |
计算各适配视图的 n 元笛卡尔积所得的元组组成的 view (类模板) (定制点对象) | |
连接所适配各视图而组成的 view (类模板) (定制点对象) | |
[编辑] 范围生成器
| 在标头
<generator> 定义 | |
| 在命名空间
std 定义 | |
| (C++23) |
表示同步协程生成器的 view (类模板) |
[编辑] 辅助项
[编辑] 范围适配器对象
见范围适配器对象 (RangeAdaptorObject) (RAO)。
[编辑] 范围适配器闭包对象
见范围适配器闭包对象 (RangeAdaptorClosureObject) (RACO)。
[编辑] 定制点对象
见定制点对象(CPO)。
[编辑] 可赋值的包装器
某些范围适配器使用 可复制包装 (C++23 前)可移动包装 (C++23 起) 包装其元素或函数对象。必要时,包装器会以可赋值性增强被包装对象。
[编辑] 非传播缓存
某些范围适配器是通过 non-propagating-cache 这一仅用于阐述的类模板指定的,其行为几乎与 std::optional<T> 完全相同(不同之处请参见说明)。
| 本节未完成 原因:为 non-propagating-cache 创建单独的页 [range.nonprop.cache] |
[编辑] 定制点对象辅助模板
| template< ranges::input_range R > constexpr auto& /* possibly-const-range */(R& r) noexcept |
(1) | (仅用于阐述*) |
| template< class T > constexpr auto /* as-const-pointer */( const T* p ) noexcept |
(2) | (仅用于阐述*) |
某些范围访问定制点对象是根据这些仅用于阐述的函数模板指定的。
[编辑] 范围适配器辅助模板
| template< class F, class Tuple > constexpr auto /* tuple-transform */( F&& f, Tuple&& tuple ) |
(1) | (仅用于阐述*) |
| template< class F, class Tuple > constexpr void /* tuple-for-each */( F&& f, Tuple&& tuple ) |
(2) | (仅用于阐述*) |
| template< class T > constexpr T& /* as-lvalue */( T&& t ) |
(3) | (仅用于阐述*) |
有些范围适配器是用这些仅用于阐述的函数模板指定的。
[编辑] 辅助概念
以下仅用于阐述的概念用于几种类型,但它们不是标准库接口的一部分。
| template< class R > concept /* simple-view */ = |
(1) | (仅用于阐述*) |
| template< class I > concept /* has-arrow */ = |
(2) | (仅用于阐述*) |
| template< class T, class U > concept /* different-from */ = |
(3) | (仅用于阐述*) |
| template< class R > concept /* range-with-movable-references */ = |
(4) | (仅用于阐述*) |
[编辑] 注解
| 功能特性测试宏 | 值 | 标准 | 功能特性 |
|---|---|---|---|
__cpp_lib_generator |
202207L | (C++23) | std::generator – 适用于范围的同步协程生成器 |
__cpp_lib_ranges |
201911L | (C++20) | 范围库和受约束算法 |
| 202106L | (C++20) (DR) |
非 默认可初始化 视图 | |
| 202110L | (C++20) (DR) |
带所有权视图 | |
| 202202L | (C++23) | std::ranges::range_adaptor_closure | |
| 202207L | (C++23) | 放松范围适配器以允许仅移动类型 | |
| 202211L | (C++23) | 移除 “毒药丸” (P2602):ranges::begin 等的重载 | |
__cpp_lib_ranges_as_const |
202207L | (C++23) | std::const_iterator, std::ranges::as_const_view |
__cpp_lib_ranges_as_rvalue |
202207L | (C++23) | std::ranges::as_rvalue_view |
__cpp_lib_ranges_cartesian_product |
202207L | (C++23) | std::ranges::cartesian_product_view |
__cpp_lib_ranges_chunk |
202202L | (C++23) | std::ranges::chunk_view |
__cpp_lib_ranges_chunk_by |
202202L | (C++23) | std::ranges::chunk_by_view |
__cpp_lib_ranges_concat |
202403L | (C++26) | std::ranges::concat_view |
__cpp_lib_ranges_enumerate |
202302L | (C++23) | std::ranges::enumerate_view |
__cpp_lib_ranges_join_with |
202202L | (C++23) | std::ranges::join_with_view |
__cpp_lib_ranges_repeat |
202207L | (C++23) | std::ranges::repeat_view |
__cpp_lib_ranges_slide |
202202L | (C++23) | std::ranges::slide_view |
__cpp_lib_ranges_stride |
202207L | (C++23) | std::ranges::stride_view |
__cpp_lib_ranges_to_container |
202202L | (C++23) | std::ranges::to |
__cpp_lib_ranges_zip |
202110L | (C++23) | std::ranges::zip_view, std::ranges::zip_transform_view, std::ranges::adjacent_view, std::ranges::adjacent_transform_view |
[编辑] 示例
#include <iostream> #include <ranges> int main() { auto const ints = {0, 1, 2, 3, 4, 5}; auto even = [](int i) { return 0 == i % 2; }; auto square = [](int i) { return i * i; }; // 组合视图的“管道”语法: for (int i : ints | std::views::filter(even) | std::views::transform(square)) std::cout << i << ' '; std::cout << '\n'; // 传统的“函数式”组合语法: for (int i : std::views::transform(std::views::filter(ints, even), square)) std::cout << i << ' '; }
输出:
0 4 16 0 4 16
[编辑] 缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
|---|---|---|---|
| LWG 3509 (P2281R1) |
C++20 | 不明确范围适配器对象如何绑定尾随参数 | 按值绑定它们 |
| LWG 3948 | C++23 | possibly-const-range 和 as-const-pointer 没有声明 noexcept
|
声明 noexcept |

