命名空间
变体
操作

范围库 (C++20 起)

来自 cppreference.cn
< cpp
 
 
范围库 (Ranges library)
范围适配器 (Range adaptors)
(C++23)(C++23)
(C++23)
(C++23)(C++23)
(C++23)(C++23)
(C++23)(C++23)
(C++23)(C++23)

 

范围库是算法和迭代器库的扩展和泛化,通过使其可组合且不易出错,从而使其功能更强大。

该库创建和操作范围 _视图_,它们是间接表示可迭代序列(_范围_)的轻量级对象。范围是基于以下概念的抽象:

  • [beginend) – 迭代器对,例如通过从容器隐式转换创建的范围。所有接受迭代器对的算法现在都具有接受范围的重载(例如 ranges::sort
  • begin + [0size) – 计数序列,例如 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++20)
返回等于范围大小的整数
(定制点对象)[编辑]
(C++20)
返回等于范围大小的有符号整数
(定制点对象)[编辑]
(C++20)
检查范围是否为空
(定制点对象)[编辑]
(C++20)
获取指向连续范围开头的指针
(定制点对象)[编辑]
(C++20)
获取指向只读连续范围开头的指针
(定制点对象)[编辑]
范围原语 (Range primitives)
定义于头文件 <ranges>
获取范围的迭代器和哨兵类型
(别名模板)[编辑]
获取范围的大小、差值和值类型
(别名模板)[编辑]
获取范围的引用类型
(别名模板)[编辑]
悬空迭代器处理 (Dangling iterator handling)
定义于头文件 <ranges>
一个占位符类型,指示迭代器或 subrange 不应返回,因为它会悬空
(类) [编辑]
获取 borrowed_range 的迭代器类型或 subrange 类型
(别名模板)[编辑]
其他实用工具
定义于头文件 <ranges>
将范围标记为序列而不是单个值
(类模板) [编辑]
范围概念 (Range concepts)
定义于头文件 <ranges>
(C++20)
指定类型为范围,即它提供 begin 迭代器和 end 哨兵
(概念) [编辑]
指定类型为 range,并且从其表达式获得的迭代器可以安全返回而不会有悬空的危险
(概念) [编辑]
指定范围可以在常数时间内估算其大小
(概念) [编辑]
指定范围在常数时间内知道其大小
(概念) [编辑]
(C++20)
指定范围是视图,即它具有常数时间复制/移动/赋值
(概念) [编辑]
指定其迭代器类型满足 input_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 output_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 forward_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 bidirectional_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 random_access_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 contiguous_iterator 的范围
(概念) [编辑]
指定范围具有相同的迭代器和哨兵类型
(概念) [编辑]
指定 range 安全转换为 view 的要求
(概念) [编辑]
指定范围具有只读元素
(概念) [编辑]
范围转换 (Range conversions)
定义于头文件 <ranges>
(C++23)
从输入范围构造新的非视图对象
(函数模板) [编辑]
视图
定义于头文件 <ranges>
用于使用奇异递归模板模式定义view的辅助类模板
(类模板) [编辑]
将迭代器-哨兵对组合成view
(类模板) [编辑]

[编辑] 范围工厂

定义于头文件 <ranges>
定义于命名空间std::ranges
一个不含元素的空 view
(类模板) (变量模板)[编辑]
一个包含单个指定值的 view
(类模板) (定制点对象)[编辑]
由重复递增初始值生成的序列组成的 view
(类模板) (定制点对象)[编辑]
一个由重复生成相同值组成的view
(类模板) (定制点对象)[编辑]
一个view,由在相关输入流上连续应用 operator>> 获得的元素组成
(类模板) (定制点对象)[编辑]

[编辑] 范围适配器

定义于头文件 <ranges>
定义于命名空间std::ranges
用于定义范围适配器闭包对象的辅助基类模板
(类模板) [编辑]
包含range所有元素的view
(别名模板) (范围适配器对象)[编辑]
其他range元素的view
(类模板) [编辑]
一个具有对某些range的唯一所有权的view
(类模板) [编辑]
序列的 view,将每个元素转换为右值
(类模板) (范围适配器对象)[编辑]
一个 view,由满足谓词的 range 的元素组成
(类模板) (范围适配器对象)[编辑]
一个将转换函数应用于每个元素的序列 view
(类模板) (范围适配器对象)[编辑]
由另一个view的前N个元素组成的view
(类模板) (范围适配器对象)[编辑]
一个view,由另一个view的初始元素组成,直到第一个谓词返回false的元素
(类模板) (范围适配器对象)[编辑]
由另一个view的元素组成的view,跳过前N个元素
(类模板) (范围适配器对象)[编辑]
一个view,由另一个view的元素组成,跳过初始子序列元素,直到第一个谓词返回false的元素
(类模板) (范围适配器对象)[编辑]
一个view,由展平rangesview获得的序列组成
(类模板) (范围适配器对象)[编辑]
一个 view,由扁平化范围视图获得的序列组成,元素之间带有分隔符
(类模板) (范围适配器对象)[编辑]
一个 view,包含通过分隔符拆分另一个 view 获得的子范围
(类模板) (范围适配器对象)[编辑]
一个 view,包含通过分隔符拆分另一个 view 获得的子范围
(类模板) (范围适配器对象)[编辑]
一个 view,由连接的适配器视图组成
(类模板) (定制点对象)[编辑]
(C++20)
从迭代器和计数创建子范围
(定制点对象)[编辑]
view 转换为 common_range
(类模板) (范围适配器对象)[编辑]
一个view,它以反向顺序迭代另一个双向视图的元素
(类模板) (范围适配器对象)[编辑]
view 转换为 constant_range
(类模板) (范围适配器对象)[编辑]
接受一个由_tuple-like_值和数字N组成的view,并生成一个由每个元组的Nth元素组成的view
(类模板) (范围适配器对象)[编辑]
接受一个由类似对的值组成的view,并生成一个由每对的第一个元素组成的view
(类模板) (范围适配器对象)[编辑]
接受一个由类似对的值组成的view,并生成一个由每对的第二个元素组成的view
(类模板) (范围适配器对象)[编辑]
一个view,它将适配序列的每个元素映射到元素的索引和值的元组
(类模板) (范围适配器对象)[编辑]
一个由引用到适配视图对应元素的元组组成的 view
(类模板) (定制点对象)[编辑]
一个由转换函数应用于适配视图中对应元素的结果组成的 view
(类模板) (定制点对象)[编辑]
一个 view,由适配视图相邻元素的引用元组组成
(类模板) (范围适配器对象)[编辑]
一个 view,由对适配视图的相邻元素应用转换函数的结果组成
(类模板) (范围适配器对象)[编辑]
一个 view 的范围,它是另一个 view 元素的 N 大小的非重叠连续块
(类模板) (范围适配器对象)[编辑]
一个view,其Mth元素是一个覆盖另一个view的Mth到(M + N - 1)th元素的view
(类模板) (范围适配器对象)[编辑]
view分割成子范围,位于给定谓词返回false的每对相邻元素之间
(类模板) (范围适配器对象)[编辑]
一个 view,由另一个 view 的元素组成,每次前进 N 个元素
(类模板) (范围适配器对象)[编辑]
一个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 )
{
    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*/ 返回 r 的 const 限定版本,如果 const R 建模 input_range;否则,不进行任何类型转换返回 r
2) /*as-const-pointer*/ 返回指向 const 类型对象的指针。

[编辑] 范围适配器辅助函数

template< class F, class Tuple >

constexpr auto /*tuple-transform*/( 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 /*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 )
{
    return static_cast<T&>(t);

}
(3) (仅作说明*)

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

1) /*tuple-transform*/ 返回一个新的元组,该元组是通过将 f 应用于 tuple 的每个元素而构造的。
2) /*tuple-for-each*/f 应用于 tuple 的每个元素,不返回任何内容。
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_generator 202207L (C++23) std::generator – 范围的同步协程生成器
__cpp_lib_ranges 201911L (C++20) Ranges 库和 受限算法
202106L (C++23)
(DR20)
不可默认初始化视图
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)
移除间接可调用概念中的 common reference 要求
__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_hintranges::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; };
 
    // 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++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
LWG 3509
(P2281R1)
C++20 不清楚范围适配器对象如何绑定尾随参数 它们按值绑定
按值
LWG 3948 C++23 possibly-const-rangeas-const-pointer
未声明为 noexcept
声明为 noexcept
LWG 4027 C++23 对于已建模 constant_range 的范围,possibly-const-range 不会添加 const-限定符
对于已建模 constant_range 的范围,possibly-const-range 不会添加 const-限定符
为这些范围添加 const-限定符
为这些范围
LWG 4112 C++20 has-arrow 不要求 i 为 const-限定符 要求

[编辑] 参见