Namespaces
Variants

Ranges library (since C++20)

From cppreference.net
Ranges library
Range adaptors

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>
返回指向范围起始位置的迭代器
(定制点对象)
返回指示范围末尾的哨兵
(定制点对象)
返回指向只读范围起始的迭代器
(定制点对象)
返回指示只读范围末尾的哨兵
(定制点对象)
返回指向范围的反向迭代器
(定制点对象)
返回指向范围的反向末端迭代器
(定制点对象)
返回指向只读范围的反向迭代器
(定制点对象)
返回指向只读范围的反向末端迭代器
(定制点对象)
返回等于范围给出的预留提示的整数值
(定制点对象)
返回等于范围大小的整数值
(定制点对象)
返回等于范围大小的有符号整数
(定制点对象)
检查范围是否为空
(定制点对象)
获取指向连续范围起始位置的指针
(定制点对象)
获取指向只读连续范围起始位置的指针
(定制点对象)
区间原语
定义于头文件 <ranges>
获取范围的迭代器和哨兵类型
(别名模板)
获取范围的大小类型、差值类型和值类型
(别名模板)
获取范围的引用类型
(别名模板)
悬垂迭代器处理
定义于头文件 <ranges>
占位符类型,指示迭代器或 subrange 不应被返回,否则将产生悬垂引用
(类)
获取 borrowed_range 的迭代器类型或 subrange 类型
(别名模板)
其他工具
定义于头文件 <ranges>
标记一个范围以作为序列而非单个值处理
(类模板)
区间概念
定义于头文件 <ranges>
指定类型为范围,即它提供 begin 迭代器和 end 哨位
(概念)
指定类型为 range 且从其表达式获取的迭代器可安全返回而不会产生悬垂风险
(concept)
指定范围能在常数时间内估算其大小
(概念)
指定范围能在常数时间内获知其大小
(概念)
指定一个范围是视图,即具有常数时间复制/移动/赋值操作
(概念)
指定其迭代器类型满足 input_iterator 要求的范围
(概念)
指定其迭代器类型满足 output_iterator 要求的范围
(概念)
指定其迭代器类型满足 forward_iterator 要求的范围
(概念)
指定其迭代器类型满足 bidirectional_iterator 要求的范围
(概念)
指定其迭代器类型满足 random_access_iterator 的范围
(概念)
指定其迭代器类型满足 contiguous_iterator 的区间
(概念)
指定一个范围具有相同的迭代器和哨兵类型
(concept)
规定 range 能够安全转换为 view 所需满足的要求
(concept)
指定一个范围具有只读元素
(概念)
范围转换
定义于头文件 <ranges>
(C++23)
从输入范围构造新的非视图对象
(函数模板)
视图
定义于头文件 <ranges>
用于定义 view 的辅助类模板,采用 奇异递归模板模式
(类模板)
将迭代器-哨位对组合成一个 view
(类模板)

范围工厂

定义于头文件 <ranges>
定义于命名空间 std::ranges
不含任何元素的空 view
(类模板) (变量模板)
包含单个指定值元素的 view
(类模板) (定制点对象)
通过重复递增初始值生成的序列组成的 view
(类模板) (定制点对象)
通过重复生成相同值产生的序列组成的 view
(类模板) (定制点对象)
通过对关联输入流连续应用 operator>> 操作所获元素组成的 view
(类模板) (定制点对象)

范围适配器

定义于头文件 <ranges>
定义于 命名空间 std::ranges
用于定义范围适配器闭包对象的辅助基类模板
(类模板)
包含 range 所有元素的 view
(别名模板) (范围适配器对象)
某个其他 range 元素的 view
(类模板)
一个 view ,唯一拥有某个 range
(类模板)
将序列中每个元素转换为右值的 view
(类模板) (范围适配器对象)
一个由满足谓词条件的 range 元素组成的 view
(类模板) (范围适配器对象)
对序列中每个元素应用转换函数的 view
(类模板) (范围适配器对象)
一个由另一个 view 的前 N 个元素组成的 view
(类模板) (范围适配器对象)
一个由另一个 view 的初始元素组成的 view ,直到谓词首次返回 false 的元素为止
(类模板) (范围适配器对象)
一个由另一个 view 的元素组成的 view ,跳过前N个元素
(类模板) (范围适配器对象)
一个由另一个 view 的元素组成的 view ,跳过初始元素子序列直到首个谓词返回 false 的元素
(类模板) (范围适配器对象)
一个由展平 view 的序列组成的 view ,该序列来自 range s 的视图
(类模板) (范围适配器对象)
一个 view ,由展平范围视图获得的序列组成,元素之间包含分隔符
(类模板) (范围适配器对象)
通过使用分隔符拆分另一个 view 所获得的子范围构成的 view
(类模板) (范围适配器对象)
通过使用分隔符拆分另一个 view 所获得的子范围构成的 view
(类模板) (范围适配器对象)
一个由适配视图串联组成的 view
(类模板) (定制点对象)
从迭代器和计数创建子范围
(定制点对象)
view 转换为 common_range
(类模板) (范围适配器对象)
一个对另一个双向视图中的元素进行反向迭代的 view
(类模板) (范围适配器对象)
view 转换为 constant_range
(类模板) (范围适配器对象)
获取由 view 组成的 tuple-like 值和一个数字 N,生成每个元组第 N th 个元素的 view
(类模板) (范围适配器对象)
获取由键值对组成的 view 并生成包含每个键值对中首元素的 view
(类模板) (范围适配器对象)
获取由键值对组成的 view ,生成仅包含每个键值对中第二个元素的 view
(类模板) (范围适配器对象)
将适配序列的每个元素映射为包含元素位置和值的元组 view
(类模板) (范围适配器对象)
由对应被适配视图元素的引用元组组成的 view
(类模板) (定制点对象)
一个由应用转换函数到被适配视图的对应元素所生成结果组成的 view
(类模板) (定制点对象)
一个由对适配视图相邻元素的引用元组组成的 view
(类模板) (范围适配器对象)
一个由对适配视图的相邻元素应用转换函数的结果组成的 view
(类模板) (范围适配器对象)
由另一个 view 的元素组成的 N 大小非重叠连续区块的 view 范围
(类模板) (范围适配器对象)
一个 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 )
{
return static_cast < /*make-unsigned-like-t*/ < T >> ( t ) ;

}
(3) ( 仅用于说明* )
1) 对于 整数类型 T
  • T 是整数类型, /*make-signed-like-t*/ < T > 即为 std:: make_signed_t < T >
  • 否则, /*make-signed-like-t*/ < T > 为与 T 同宽度的未指定对应有符号整数类型。
2) 对于整数类类型 T
  • T 是整数类型, /*make-unsigned-like-t*/ < T > 即为 std:: make_unsigned_t < T >
  • 否则, /*make-signed-like-t*/ < T > 为与 T 等宽的对应未指定无符号整数类类型。
3) 显式转换 t /*make-unsigned-like-t*/ < T >

定制点对象辅助工具

template < ranges:: input_range R >

constexpr auto & /*possibly-const-range*/ ( R & r ) noexcept
{
if constexpr ( ranges:: input_range < const R > )
return const_cast < const R & > ( r ) ;
else
return r ;

}
(1) ( 仅用于说明* )
template < class T >

constexpr auto /*as-const-pointer*/ ( const T * p ) noexcept
{
return p ;

}
(2) ( 仅用于说明* )

某些范围访问定制点对象是根据这些仅用于说明的函数模板来指定的。

1) /*possibly-const-range*/ 如果 const R 满足 input_range 概念,则返回 r 的常量限定版本;否则直接返回 r 而不进行任何类型转换。
2) /*as-const-pointer*/ 返回指向常量类型对象的指针。

范围适配器辅助工具

template < class F, class Tuple >

constexpr auto /*元组转换*/ ( F && f, Tuple && tuple )
{
return std:: apply ( [ & ] < class ... Ts > ( Ts && ... args )
{
return std:: tuple < std:: invoke_result_t < F & , Ts > ... >
( std:: invoke ( f, std:: forward < Ts > ( args ) ) ... ) ;
} , std:: forward < Tuple > ( tuple ) ) ;

}
(1) ( 仅用于说明* )
template < class F, class Tuple >

constexpr void /*元组遍历*/ ( F && f, Tuple && tuple )
{
std:: apply ( [ & ] < class ... Ts > ( Ts && ... args )
{
( static_cast < void > ( std:: invoke ( f, std:: forward < Ts > ( args ) ) ) , ... ) ;
} , std:: forward < Tuple > ( tuple ) ) ;

}
(2) ( 仅用于说明* )
template < class T >

constexpr T & /*作为左值*/ ( T && t )
{
return static_cast < T & > ( t ) ;

}
(3) ( 仅用于说明* )

一些范围适配器是根据这些仅用于说明的函数模板来指定的。

1) /*tuple-transform*/ 返回通过将 f 应用于 tuple 的每个元素而构造的新元组。
2) /*tuple-for-each*/ tuple 中的每个元素应用 f 且不返回任何内容。
3) /*as-lvalue*/ 将右值 t 作为左值转发。

辅助概念

以下仅用于说明的概念被用于多种类型,但它们并非标准库接口的组成部分。

template < class R >

concept /*简单视图*/ =
ranges:: view < R > && ranges:: range < const R > &&
std:: same_as < ranges:: iterator_t < R > , ranges:: iterator_t < const R >> &&

std:: same_as < ranges:: sentinel_t < R > , ranges:: sentinel_t < const R >> ;
(1) ( 仅用于说明* )
template < class I >

concept /*has-arrow*/ =
ranges :: input_iterator < I > &&

( std:: is_pointer_v < I > || requires ( const I i ) { i. operator - > ( ) ; } ) ;
(2) ( 仅用于说明* )
template < class T, class U >

concept /*different-from*/ =

! std:: same_as < std:: remove_cvref_t < T > , std:: remove_cvref_t < U >> ;
(3) ( 仅用于说明* )
(4) ( 仅用于说明* )
template < bool C, class ... Views >

concept /*all-random-access*/ =
( ranges:: random_access_range

< std:: conditional_t < C, const Views, Views >> && ... ) ;
(5) ( 仅用于说明* )
template < bool C, class ... Views >

concept /*全双向迭代*/ =
( ranges:: bidirectional_range

< std:: conditional_t < C, const Views, Views >> && ... ) ;
(6) ( 仅用于说明* )
template < bool C, class ... Views >

concept /*全前向*/ =
( ranges:: forward_range

< std:: conditional_t < C, const Views, Views >> && ... ) ;
(7) ( 仅用于说明* )

注释

功能测试 标准 功能特性
__cpp_lib_generator 202207L (C++23) std:: generator 用于范围的同步协程生成器
__cpp_lib_ranges 201911L (C++20) 范围库及 约束算法
202106L (C++23)
(DR20)
default-initializable views
202110L (C++23)
(DR20)
视图 所有权
202202L (C++23) ranges:: range_adaptor_closure
202207L (C++23) 放宽 范围适配器 以支持仅移动类型
202211L (C++23) 移除 ranges:: begin 等函数中的"毒丸" (P2602) 重载
202302L (C++23) 放宽范围以允许特定投影
202406L (C++26)
(DR20)
移除间接可调用概念中的公共引用要求
__cpp_lib_ranges_as_const 202207L (C++23) std:: const_iterator ranges:: as_const_view
__cpp_lib_ranges_as_rvalue 202207L (C++23) ranges:: as_rvalue_view
__cpp_lib_ranges_cache_latest 202411L (C++26) ranges :: cache_latest_view
__cpp_lib_ranges_cartesian_product 202207L (C++23) ranges:: cartesian_product_view
__cpp_lib_ranges_chunk 202202L (C++23) ranges:: chunk_view
__cpp_lib_ranges_chunk_by 202202L (C++23) ranges:: chunk_by_view
__cpp_lib_ranges_concat 202403L (C++26) ranges:: concat_view
__cpp_lib_ranges_enumerate 202302L (C++23) ranges :: enumerate_view
__cpp_lib_ranges_join_with 202202L (C++23) ranges:: join_with_view
__cpp_lib_ranges_repeat 202207L (C++23) ranges:: repeat_view
__cpp_lib_ranges_reserve_hint 202502L (C++26) ranges :: reserve_hint ranges :: approximately_sized_range
__cpp_lib_ranges_slide 202202L (C++23) ranges:: slide_view
__cpp_lib_ranges_stride 202207L (C++23) ranges:: stride_view
__cpp_lib_ranges_to_container 202202L (C++23) ranges:: to
__cpp_lib_ranges_to_input 202502L (C++26) ranges :: to_input_view
__cpp_lib_ranges_zip 202110L (C++23) ranges:: zip_view
ranges:: zip_transform_view
ranges:: adjacent_view
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++标准。

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 具有常量限定 要求具有常量限定

另请参阅