范围库 (C++20 起)

来自cppreference.com
< cpp


 
 
范围库
范围适配器
 

范围库是对迭代器和泛型算法库的一个扩展,使得迭代器和算法可以通过组合变得更强大,并且减少错误。

范围库创造并操作范围视图,它们是间接表示可遍历的序列(范围)的轻量对象。 范围是对以下内容的抽象:

  • [beginend) – 迭代器对,例如,范围可以从容器隐式转换而得。所有接受迭代器对的算法现在都有接受范围的重载(例如 ranges::sort
  • begin + [0size) – 计数的序列,例如 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> 定义
返回指向范围起始的迭代器
(定制点对象)[编辑]
返回指示范围结尾的哨位
(定制点对象)[编辑]
返回指向只读范围起始的迭代器
(定制点对象)[编辑]
返回指示只读范围结尾的哨位
(定制点对象)[编辑]
返回指向范围的逆向迭代器
(定制点对象)[编辑]
返回指向范围的逆向尾迭代器
(定制点对象)[编辑]
返回指向只读范围的逆向迭代器
(定制点对象)[编辑]
返回指向只读范围的逆向尾迭代器
(定制点对象)[编辑]
返回等于给定范围的预备储存提示的整数
(定制点对象)[编辑]
返回等于范围大小的整数
(定制点对象)[编辑]
返回等于范围大小的有符号整数
(定制点对象)[编辑]
检查范围是否为空
(定制点对象)[编辑]
获得指向连续范围的起始的指针
(定制点对象)[编辑]
获得指向只读连续范围的起始的指针
(定制点对象)[编辑]
范围原语
在标头 <ranges> 定义
获取范围的迭代器和哨位类型
(别名模板)[编辑]
取得范围的大小类型、差类型和值类型
(别名模板)[编辑]
取得范围的引用类型
(别名模板)[编辑]
悬垂迭代器处理
在标头 <ranges> 定义
占位类型,指示不应返回迭代器或子范围,因为它可能悬垂
(类)[编辑]
获得塑造 borrowed_range 的迭代器类型或子范围类型
(别名模板)[编辑]
其他工具
在标头 <ranges> 定义
标记范围为当作序列而非单个值对待
(类模板)[编辑]
范围概念
在标头 <ranges> 定义
指定类型为范围,即它同时提供 begin 迭代器和 end 哨位
(概念)[编辑]
指定类型为 range 而且能安全返回从该类型表达式获得的迭代器而无需担心悬垂
(概念)[编辑]
指定范围可以常数时间估算大小
(概念)[编辑]
指定范围可以常数时间计算大小
(概念)[编辑]
指定范围为视图,即它拥有常数时间的复制/移动/赋值
(概念)[编辑]
指定范围的迭代器类型满足 input_iterator
(概念)[编辑]
指定范围的迭代器类型满足 output_iterator
(概念)[编辑]
指定范围的迭代器类型满足 forward_iterator
(概念)[编辑]
指定范围的迭代器类型满足 bidirectional_iterator
(概念)[编辑]
指定范围的迭代器类型满足 random_access_iterator
(概念)[编辑]
指定范围的迭代器类型满足 contiguous_iterator
(概念)[编辑]
指定范围拥有相同的迭代器和哨位类型
(概念)[编辑]
指定针对 range 的要求,令其可安全转换为 view
(概念)[编辑]
指定范围的所有元素只读
(概念)[编辑]
范围转换
在标头 <ranges> 定义
(C++23)
从输入范围构造一个新的非视图对象
(函数模板)[编辑]
视图
在标头 <ranges> 定义
用于定义 view 的辅助类模板,使用奇特重现模板模式
(类模板)[编辑]
将迭代器/哨位对结合为一个 view
(类模板)[编辑]

[编辑]范围工厂

在标头 <ranges> 定义
在命名空间 std::ranges 定义
无元素的空 view
(类模板)(变量模板)[编辑]
含有具有指定值的单个元素的 view
(类模板)(定制点对象)[编辑]
由通过重复对某个初值自增所生成的序列组成的 view
(类模板)(定制点对象)[编辑]
由重复产出同一值生成的序列组成的 view
(类模板)(定制点对象)[编辑]
由在关联的输入流上相继应用 operator>> 获得的元素组成的 view
(类模板)(定制点对象)[编辑]

[编辑]范围适配器

在标头 <ranges> 定义
在命名空间 std::ranges 定义
用于定义范围适配器闭包对象的辅助基类模板
(类模板)[编辑]
包含 range 的所有元素的 view
(别名模板)(范围适配器对象)[编辑]
某个其他 range 的元素的 view
(类模板)[编辑]
拥有某 range 的独占所有权的 view
(类模板)[编辑]
由将序列所有元素转换为右值组成的 view
(类模板)(范围适配器对象)[编辑]
range 中满足某个谓词的元素构成的 view
(类模板)(范围适配器对象)[编辑]
对序列的每个元素应用某个变换函数的 view
(类模板)(范围适配器对象)[编辑]
由另一 view 的前 N 个元素组成的 view
(类模板)(范围适配器对象)[编辑]
由另一 view 的到首个谓词返回 false 为止的起始元素组成的 view
(类模板)(范围适配器对象)[编辑]
由另一 view 跳过前 N 个元素组成的 view
(类模板)(范围适配器对象)[编辑]
由另一 view 跳过元素的起始序列,直至首个使谓词返回 false 的元素组成的 view
(类模板)(范围适配器对象)[编辑]
由拉平 range 组成的 view 所获得的序列构成的 view
(类模板)(范围适配器对象)[编辑]
由拉平范围组成的视图并以分隔符间隔所获得的序列构成的 view
(类模板)(范围适配器对象)[编辑]
用某个分隔符切割另一 view 所获得的子范围的 view
(类模板)(范围适配器对象)[编辑]
用某个分隔符切割另一 view 所获得的子范围的 view
(类模板)(范围适配器对象)[编辑]
连接所适配各视图而组成的 view
(类模板)(定制点对象)[编辑]
从迭代器和计数创建子范围
(定制点对象)[编辑]
转换 viewcommon_range
(类模板)(范围适配器对象)[编辑]
以逆序迭代另一双向视图上的元素的 view
(类模板)(范围适配器对象)[编辑]
转换 viewconstant_range
(类模板)(范围适配器对象)[编辑]
选取 tuple-like 值组成的 view 和数值 N,产生每个元组的第 N 个元素组成的 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
(类模板)(范围适配器对象)[编辑]
计算各适配视图的 n 元笛卡尔积所得的元组组成的 view
(类模板)(定制点对象)[编辑]
缓存其底层序列最后一次访问的元素的 view
(类模板)(范围适配器对象)[编辑]
转换 view 到仅实现 input_range 和不是 common_range 的范围
(类模板)(范围适配器对象)[编辑]

[编辑]范围生成器 (C++23 起)

在标头 <generator> 定义
在命名空间 std 定义
(C++23)
表示同步协程生成器的 view
(类模板)[编辑]

[编辑]辅助项

[编辑]范围适配器对象

范围适配器对象(RangeAdaptorObject)

[编辑]范围适配器闭包对象

范围适配器闭包对象(RangeAdaptorClosureObject)

[编辑]定制点对象

定制点对象

[编辑]可赋值的包装器

某些范围适配器使用 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 )
{
    returnstatic_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 >

constexprauto&/*possibly-const-range*/(R& r)noexcept
{
    ifconstexpr(ranges::constant_range<const R>&&
                  !ranges::constant_range<R>)
        returnconst_cast<const R&>(r);
    else
        return r;

}
(1) (仅用于阐述*)
template<class T >

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

}
(2) (仅用于阐述*)

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

1)/*possibly-const-range*/ 在是深 const 范围时返回 const 限定的范围 r;否则,返回不进行任何转型的 r
2)/*as-const-pointer*/ 返回常量类型对象的指针。

[编辑]范围适配器辅助模板

template<class F, class Tuple >

constexprauto/*tuple-transform*/( F&& f, Tuple&& tuple )
{
    returnstd::apply([&]<class... Ts>(Ts&&... args)
    {
        returnstd::tuple<std::invoke_result_t<F&, Ts>...>
            (std::invoke(f, std::forward<Ts>(args))...);
    }, std::forward<Tuple>(tuple));

}
(1) (仅用于阐述*)
template<class F, class Tuple >

constexprvoid/*tuple-for-each*/( 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&/*as-lvalue*/( T&& t )
{
    returnstatic_cast<T&>(t);

}
(3) (仅用于阐述*)

有些范围适配器是用这些仅用于阐述的函数模板指定的。

1)/*tuple-transform*/ 返回对 tuple 的每个元素应用 f 的新 tuple
2)/*tuple-for-each*/tuple 的每个元素应用 f 然后什么都不返回。
3)/*as-lvalue*/ 将右值 t 作为左值转发。

[编辑]辅助概念

以下仅用于阐述的概念用于几种类型,但它们不是标准库接口的一部分。

template<class R >

concept /*simple-view*/=
    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) (仅用于阐述*)
template<class R >

concept /*range-with-movable-references*/=
    ranges::input_range<R>&&
    std::move_constructible<ranges::range_reference_t<R>>&&

    std::move_constructible<ranges::range_rvalue_reference_t<R>>;
(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 /*all-bidirectional*/=
    (ranges::bidirectional_range

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

concept /*all-forward*/=

    (ranges::forward_range<std::conditional_t<C, const Views, Views>>&& ...);
(7) (仅用于阐述*)

[编辑]注解

功能特性测试标准功能特性
__cpp_lib_generator202207L(C++23)std::generator——适用于范围的同步协程生成器
__cpp_lib_ranges201911L(C++20)范围库和受约束算法
202106L(C++23)
(DR20)
可默认初始化视图
202110L(C++23)
(DR20)
所有权视图
202202L(C++23)ranges::range_adaptor_closure
202207L(C++23)放松范围适配器以允许仅移动类型
202211L(C++23)移除 “毒药丸” (P2602)ranges::begin 等的重载
202302L(C++23)放宽范围限制已允许使用某些投影
202406L(C++26)
(DR20)
从间接调用概念中移除公共引用要求
__cpp_lib_ranges_as_const202207L(C++23)std::const_iteratorranges::as_const_view
__cpp_lib_ranges_as_rvalue202207L(C++23)ranges::as_rvalue_view
__cpp_lib_ranges_cache_latest202411L(C++26)ranges::cache_latest_view
__cpp_lib_ranges_cartesian_product202207L(C++23)ranges::cartesian_product_view
__cpp_lib_ranges_chunk202202L(C++23)ranges::chunk_view
__cpp_lib_ranges_chunk_by202202L(C++23)ranges::chunk_by_view
__cpp_lib_ranges_concat202403L(C++26)ranges::concat_view
__cpp_lib_ranges_enumerate202302L(C++23)ranges::enumerate_view
__cpp_lib_ranges_join_with202202L(C++23)ranges::join_with_view
__cpp_lib_ranges_repeat202207L(C++23)ranges::repeat_view
__cpp_lib_ranges_reserve_hint202502L(C++26)ranges::approximately_sized_range
ranges::reserve_hint
__cpp_lib_ranges_slide202202L(C++23)ranges::slide_view
__cpp_lib_ranges_stride202207L(C++23)ranges::stride_view
__cpp_lib_ranges_to_container202202L(C++23)ranges::to
__cpp_lib_ranges_to_input202502L(C++26)ranges::to_input_view
__cpp_lib_ranges_zip202110L(C++23)ranges::zip_view,
ranges::zip_transform_view,
ranges::adjacent_view,
ranges::adjacent_transform_view


[编辑]示例

#include <iostream>#include <ranges>   int main(){autoconst ints ={0, 1, 2, 3, 4, 5};auto even =[](int i){return0== 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-rangeas-const-pointer 没有声明 noexcept 声明 noexcept
LWG 4027 C++23 possibly-const-range 不会对已实现 constant_range 的范围添加 const 限定 对此类范围添加 const 限定
LWG 4112 C++20 has-arrow 未要求 i 具有 const 限定 要求具有 const 限定

[编辑]参阅

close