范围库 (自 C++20 起)
范围库是对算法和迭代器库的扩展和泛化,通过使其可组合且不易出错,从而使其更加强大。
该库创建和操作范围视图,这是一种轻量级对象,间接表示可迭代序列(范围)。范围是对以下内容的抽象:
-
[
begin,
end)
– 迭代器对,例如通过从容器隐式转换创建的范围。所有接受迭代器对的算法现在都有接受范围的重载(例如 ranges::sort) - begin
+
[
0,
size)
– 计数序列,例如 views::counted 返回的范围 -
[
begin,
predicate)
– 条件终止序列,例如 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++26) |
返回一个等于范围给出的保留提示的整数 (自定义点对象) | |
(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) |
获取范围的大小、差值和值类型 (别名模板) | |
获取范围的引用类型 (别名模板) | ||
悬垂迭代器处理 | ||
定义于头文件
<ranges> | ||
(C++20) |
指示不应返回迭代器或 subrange 的占位符类型,因为它将是悬垂的(类) | |
获取 borrowed_range 的迭代器类型或 subrange 类型(别名模板) | ||
其他工具 | ||
定义于头文件
<ranges> | ||
(C++23) |
标记一个范围,使其被视为序列而不是单个值 (类模板) | |
范围概念 | ||
定义于头文件
<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 ,由通过重复递增初始值生成的序列组成(类模板) (自定义点对象) |
一个 view ,由通过重复产生相同值而生成的序列组成(类模板) (自定义点对象) | |
一个 view ,由通过连续应用关联输入流上的 operator>> 获取的元素组成(类模板) (自定义点对象) |
[编辑] 范围适配器
定义于头文件
<ranges> | |
定义于命名空间
std::ranges | |
用于定义范围适配器闭包对象的辅助基类模板 (类模板) | |
(C++20) |
一个 view ,包含 range 的所有元素(别名模板) (范围适配器对象) |
(C++20) |
某个其他 range 的元素的 view (类模板) |
(C++20) |
具有某些 range 的唯一所有权的 view (类模板) |
将每个元素强制转换为右值的序列的 view (类模板) (范围适配器对象) | |
由满足谓词的 range 的元素组成的 view (类模板) (范围适配器对象) | |
将转换函数应用于每个元素的序列的 view (类模板) (范围适配器对象) | |
(C++20) |
由另一个 view 的前 N 个元素组成的 view (类模板) (范围适配器对象) |
由另一个 view 的初始元素组成的 view ,直到谓词返回 false 的第一个元素(类模板) (范围适配器对象) | |
(C++20) |
由另一个 view 的元素组成的 view ,跳过前 N 个元素(类模板) (范围适配器对象) |
由另一个 view 的元素组成的 view ,跳过初始元素子序列,直到谓词返回 false 的第一个元素(类模板) (范围适配器对象) | |
(C++20) |
由从扁平化 range 的 view 获得的序列组成的 view (类模板) (范围适配器对象) |
由从扁平化范围视图获得的序列组成的 view ,元素之间带有分隔符(类模板) (范围适配器对象) | |
在通过使用分隔符拆分另一个 view 获得的子范围上的 view (类模板) (范围适配器对象) | |
在通过使用分隔符拆分另一个 view 获得的子范围上的 view (类模板) (范围适配器对象) | |
由适配视图的连接组成的 view (类模板) (自定义点对象) | |
(C++20) |
从迭代器和计数创建子范围 (自定义点对象) |
将 view 转换为 common_range (类模板) (范围适配器对象) | |
一个 view ,它以相反的顺序迭代另一个双向 view 的元素(类模板) (范围适配器对象) | |
将 view 转换为 constant_range (类模板) (范围适配器对象) | |
接受一个由 tuple-like 值和数字 N 组成的 view ,并生成一个由每个元组的第 N 个元素组成的 view (类模板) (范围适配器对象) | |
(C++20) |
接受一个由类对值组成的 view ,并生成一个由每对的第一个元素组成的 view (类模板) (范围适配器对象) |
接受一个由类对值组成的 view ,并生成一个由每对的第二个元素组成的 view (类模板) (范围适配器对象) | |
一个 view ,它将适配序列的每个元素映射到一个由元素的位置及其值组成的元组(类模板) (范围适配器对象) | |
(C++23) |
一个 view ,它由对适配的 view 的相应元素的引用的元组组成(类模板) (定制点对象) |
一个 view ,它由将变换函数应用于适配的 view 的相应元素的结果组成(类模板) (定制点对象) | |
一个 view ,它由对适配的 view 的相邻元素的引用的元组组成(类模板) (范围适配器对象) | |
一个 view ,它由将变换函数应用于适配的 view 的相邻元素的结果组成(类模板) (范围适配器对象) | |
一系列 view ,它们是另一个 view 的元素的 N 大小的非重叠连续块(类模板) (范围适配器对象) | |
一个 view ,其第 M 个元素是另一个 view 的第 M 个到第 (M + N - 1) 个元素的 view (类模板) (范围适配器对象) | |
将 view 拆分为子范围,子范围位于给定谓词返回 false 的每对相邻元素之间(类模板) (范围适配器对象) | |
一个 view ,它由另一个 view 的元素组成,每次前进 N 个元素(类模板) (范围适配器对象) | |
一个 view ,它由适配的 view 的 n 元笛卡尔积计算的结果元组组成(类模板) (定制点对象) | |
一个 view ,它缓存其底层序列的最后访问元素(类模板) (范围适配器对象) | |
将 view 转换为仅为 input_range 且非 common_range 的范围(类模板) (范围适配器对象) |
[编辑] 范围生成器 (自 C++23 起)
定义于头文件
<generator> | |
定义于命名空间
std | |
(C++23) |
一个表示同步 协程 生成器的 view (类模板) |
[编辑] 辅助项
[编辑] 范围适配器对象
参见 RangeAdaptorObject (RAO)。
[编辑] 范围适配器闭包对象
参见 RangeAdaptorClosureObject (RACO)。
[编辑] 定制点对象
参见 定制点对象 (CPO)。
[编辑] 可赋值包装器
一些范围适配器使用 copyable-box
(在 C++23 之前)movable-box
(自 C++23 起) 包装它们的元素或函数对象。当需要时,包装器使用可赋值性来增强被包装的对象。
[编辑] 非传播缓存
一些范围适配器根据仅用于演示的类模板 non-propagating-cache
指定,该模板的行为几乎类似于 std::optional<T> (参见差异描述)。
[编辑] 条件 const
类型
template< bool Const, class T > using /*maybe-const*/ = std::conditional_t<Const, const T, T>; |
(仅用于演示*) | |
别名模板 /*maybe-const*/ 是一个简写,用于有条件地将 const 限定符应用于类型 T
。
[编辑] 类整数类型辅助模板
template< /*is-integer-like*/ T > using /*make-signed-like-t*/<T> = /* 参见描述 */; |
(1) | (仅用于演示*) |
template< /*is-integer-like*/ T > using /*make-unsigned-like-t*/<T> = /* 参见描述 */; |
(2) | (仅用于演示*) |
template< /*is-integer-like*/ T > /*make-unsigned-like-t*/<T> /*to-unsigned-like*/( T t ) |
(3) | (仅用于演示*) |
T
- 如果
T
是整数类型,则 /*make-signed-like-t*/<T> 是 std::make_signed_t<T>。 - 否则,/*make-signed-like-t*/<T> 是具有与
T
相同宽度的相应未指定的类整数有符号类型。
T
- 如果
T
是整数类型,则 /*make-unsigned-like-t*/<T> 是 std::make_unsigned_t<T>。 - 否则,/*make-signed-like-t*/<T> 是具有与
T
相同宽度的相应未指定的类整数无符号类型。
[编辑] 定制点对象辅助函数
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) | (仅用于演示*) |
template< bool C, class... Views > concept /*all-random-access*/ = |
(5) | (仅用于演示*) |
template< bool C, class... Views > concept /*all-bidirectional*/ = |
(6) | (仅用于演示*) |
template< bool C, class... Views > concept /*all-forward*/ = |
(7) | (仅用于演示*) |
[编辑] 注解
[编辑] 示例
#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; }; // the "pipe" syntax of composing the views: for (int i : ints | std::views::filter(even) | std::views::transform(square)) std::cout << i << ' '; std::cout << '\n'; // a traditional "functional" composing syntax: for (int i : std::views::transform(std::views::filter(ints, even), square)) std::cout << i << ' '; }
输出
0 4 16 0 4 16
[编辑] 缺陷报告
以下行为更改缺陷报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
LWG 3509 (P2281R1) |
C++20 | 范围适配器对象如何绑定尾随参数尚不清楚 | 它们被绑定 按值 |
LWG 3948 | C++23 | possibly-const-range 和 as-const-pointer 未声明为 noexcept |
声明为 noexcept |
LWG 4027 | C++23 | possibly-const-range 不会添加 const 限定对于已经建模 constant_range 的范围 |
添加 const 限定 对于此类范围 |
LWG 4112 | C++20 | has-arrow 不要求 i 为 const 限定 |
要求 |