Ranges library (since C++20)
ranges库是算法库和迭代器库的扩展与泛化,通过使其可组合且更不易出错,从而增强其功能。
该库创建并操作范围 views ,这些轻量级对象间接表示可迭代序列( ranges )。范围是建立在
-
[起始,结束)– 迭代器对,例如通过容器隐式转换构成的区间。所有接受迭代器对的算法现在都提供了接受区间的重载版本(例如 ranges::sort ) -
起始
+[ 0 ,数量)– 计数序列,例如由 views::counted 返回的区间 -
[起始,谓词)– 条件终止序列,例如由 views::take_while 返回的区间 -
[起始,..)– 无界序列,例如由 views::iota 返回的区间
ranges库包含 范围算法 (以即时方式应用于范围)和 范围适配器 (以惰性方式应用于视图)。适配器可以组合成管道,使得它们的操作在迭代视图时执行。
|
定义于头文件
<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)
|
获取范围的大小类型、差值类型和值类型
(别名模板) |
|
|
(C++20)
(C++23)
(C++20)
(C++20)
|
获取范围的引用类型
(别名模板) |
|
悬垂迭代器处理 |
||
|
定义于头文件
<ranges>
|
||
|
(C++20)
|
占位符类型,指示迭代器或
subrange
不应被返回,否则将产生悬垂引用
(类) |
|
获取
borrowed_range
的迭代器类型或
subrange
类型
(别名模板) |
||
其他工具 |
||
|
定义于头文件
<ranges>
|
||
|
(C++23)
|
标记一个范围以作为序列而非单个值处理
(类模板) |
|
区间概念 |
||
|
定义于头文件
<ranges>
|
||
|
(C++20)
|
指定类型为范围,即它提供
begin
迭代器和
end
哨位
(概念) |
|
|
(C++20)
|
指定类型为
range
且从其表达式获取的迭代器可安全返回而不会产生悬垂风险
(concept) |
|
|
指定范围能在常数时间内估算其大小
(概念) |
||
|
(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)
|
指定一个范围具有相同的迭代器和哨兵类型
(concept) |
|
|
(C++20)
|
规定
range
能够安全转换为
view
所需满足的要求
(concept) |
|
|
(C++23)
|
指定一个范围具有只读元素
(概念) |
|
范围转换 |
||
|
定义于头文件
<ranges>
|
||
|
(C++23)
|
从输入范围构造新的非视图对象
(函数模板) |
|
视图 |
||
|
定义于头文件
<ranges>
|
||
|
(C++20)
|
用于定义
view
的辅助类模板,采用
奇异递归模板模式
(类模板) |
|
|
(C++20)
|
将迭代器-哨位对组合成一个
view
(类模板) |
|
范围工厂
|
定义于头文件
<ranges>
|
|
|
定义于命名空间
std::ranges
|
|
|
(C++20)
|
不含任何元素的空
view
(类模板) (变量模板) |
包含单个指定值元素的
view
(类模板) (定制点对象) |
|
|
(C++20)
|
通过重复递增初始值生成的序列组成的
view
(类模板) (定制点对象) |
通过重复生成相同值产生的序列组成的
view
(类模板) (定制点对象) |
|
通过对关联输入流连续应用
operator>>
操作所获元素组成的
view
(类模板) (定制点对象) |
|
范围适配器
|
定义于头文件
<ranges>
|
|
|
定义于 命名空间
std::ranges
|
|
|
(C++23)
|
用于定义范围适配器闭包对象的辅助基类模板
(类模板) |
|
(C++20)
|
包含
range
所有元素的
view
(别名模板) (范围适配器对象) |
|
(C++20)
|
某个其他
range
元素的
view
(类模板) |
|
(C++20)
|
一个
view
,唯一拥有某个
range
(类模板) |
将序列中每个元素转换为右值的
view
(类模板) (范围适配器对象) |
|
一个由满足谓词条件的
range
元素组成的
view
(类模板) (范围适配器对象) |
|
对序列中每个元素应用转换函数的
view
(类模板) (范围适配器对象) |
|
|
(C++20)
|
一个由另一个
view
的前 N 个元素组成的
view
(类模板) (范围适配器对象) |
一个由另一个
view
的初始元素组成的
view
,直到谓词首次返回
false
的元素为止
(类模板) (范围适配器对象) |
|
|
(C++20)
|
一个由另一个
view
的元素组成的
view
,跳过前N个元素
(类模板) (范围适配器对象) |
一个由另一个
view
的元素组成的
view
,跳过初始元素子序列直到首个谓词返回
false
的元素
(类模板) (范围适配器对象) |
|
|
(C++20)
|
一个由展平
view
的序列组成的
view
,该序列来自
range
s
的视图
(类模板) (范围适配器对象) |
一个
view
,由展平范围视图获得的序列组成,元素之间包含分隔符
(类模板) (范围适配器对象) |
|
通过使用分隔符拆分另一个
view
所获得的子范围构成的
view
(类模板) (范围适配器对象) |
|
|
(C++20)
|
通过使用分隔符拆分另一个
view
所获得的子范围构成的
view
(类模板) (范围适配器对象) |
一个由适配视图串联组成的
view
(类模板) (定制点对象) |
|
|
(C++20)
|
从迭代器和计数创建子范围
(定制点对象) |
将
view
转换为
common_range
(类模板) (范围适配器对象) |
|
一个对另一个双向视图中的元素进行反向迭代的
view
(类模板) (范围适配器对象) |
|
将
view
转换为
constant_range
(类模板) (范围适配器对象) |
|
获取由
view
组成的
tuple-like
值和一个数字 N,生成每个元组第 N
th
个元素的
view
(类模板) (范围适配器对象) |
|
|
(C++20)
|
获取由键值对组成的
view
并生成包含每个键值对中首元素的
view
(类模板) (范围适配器对象) |
获取由键值对组成的
view
,生成仅包含每个键值对中第二个元素的
view
(类模板) (范围适配器对象) |
|
将适配序列的每个元素映射为包含元素位置和值的元组
view
(类模板) (范围适配器对象) |
|
|
(C++23)
|
由对应被适配视图元素的引用元组组成的
view
(类模板) (定制点对象) |
一个由应用转换函数到被适配视图的对应元素所生成结果组成的
view
(类模板) (定制点对象) |
|
一个由对适配视图相邻元素的引用元组组成的
view
(类模板) (范围适配器对象) |
|
一个由对适配视图的相邻元素应用转换函数的结果组成的
view
(类模板) (范围适配器对象) |
|
|
(C++23)
|
由另一个
view
的元素组成的
N
大小非重叠连续区块的
view
范围
(类模板) (范围适配器对象) |
|
(C++23)
|
一个
view
,其第 M
个
元素是另一个
view
中第 M
个
至第 (M + N - 1)
个
元素的
view
(类模板) (范围适配器对象) |
将
view
分割为子范围,分割位置位于每一对相邻元素之间,当给定谓词返回
false
(类模板) (范围适配器对象) |
|
一个由另一个
view
的元素组成的
view
,每次跨越 N 个元素前进
(类模板) (范围适配器对象) |
|
由适配视图的n元笛卡尔积计算结果组成的元组构成的
view
(类模板) (定制点对象) |
|
一个
view
用于缓存其底层序列最后被访问的元素
(类模板) (范围适配器对象) |
|
将
view
转换为仅支持
input_range
且非
common_range
的范围
(类模板) (范围适配器对象) |
|
范围生成器 (since C++23)
|
定义于头文件
<generator>
|
|
|
定义于命名空间
std
|
|
|
(C++23)
|
表示同步
协程
生成器的
view
(类模板) |
辅助项
范围适配器对象
参见 RangeAdaptorObject (RAO)。
范围适配器闭包对象
参见 RangeAdaptorClosureObject (RACO)。
定制点对象
参见 Customization point object (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*/
是一个用于有条件地向类型
T
应用
const
限定符的简写形式。
整数类型辅助模板
|
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
/*元组转换*/
(
F
&&
f, Tuple
&&
tuple
)
|
(1) | ( 仅用于说明* ) |
|
template
<
class
F,
class
Tuple
>
constexpr
void
/*元组遍历*/
(
F
&&
f, Tuple
&&
tuple
)
|
(2) | ( 仅用于说明* ) |
|
template
<
class
T
>
constexpr
T
&
/*作为左值*/
(
T
&&
t
)
|
(3) | ( 仅用于说明* ) |
一些范围适配器是根据这些仅用于说明的函数模板来指定的。
辅助概念
以下仅用于说明的概念被用于多种类型,但它们并非标准库接口的组成部分。
|
template
<
class
R
>
concept
/*简单视图*/
=
|
(1) | ( 仅用于说明* ) |
|
template
<
class
I
>
concept
/*has-arrow*/
=
|
(2) | ( 仅用于说明* ) |
|
template
<
class
T,
class
U
>
concept
/*different-from*/
=
|
(3) | ( 仅用于说明* ) |
|
template
<
class
R
>
concept
/*可移动引用范围*/
=
|
(4) | ( 仅用于说明* ) |
|
template
<
bool
C,
class
...
Views
>
concept
/*all-random-access*/
=
|
(5) | ( 仅用于说明* ) |
|
template
<
bool
C,
class
...
Views
>
concept
/*全双向迭代*/
=
|
(6) | ( 仅用于说明* ) |
|
template
<
bool
C,
class
...
Views
>
concept
/*全前向*/
=
|
(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; }; // 使用管道语法组合视图: 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++标准。
| 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
不会为已实现
constant_range
概念的范围添加常量限定 |
为此类范围
添加常量限定 |
| LWG 4112 | C++20 |
has-arrow
未要求
i
具有常量限定
|
要求具有常量限定 |