命名空间
变体
操作

范围库 (C++20)

来自 cppreference.com
< cpp
 
 
范围库
范围适配器
 

范围库是算法和迭代器库的扩展和概括,通过使它们可组合且减少错误,使其更强大。

该库创建和操作范围视图,即间接表示可迭代序列(范围)的轻量级对象。范围是以下内容之上的抽象:

  • [beginend) – 迭代器对,例如由容器的隐式转换生成的范围。所有接受迭代器对的算法现在都具有接受范围的重载(例如,ranges::sort
  • begin + [0size) – 计数序列,例如由 views::counted 返回的范围
  • [beginpredicate) – 条件终止序列,例如由 views::take_while 返回的范围
  • [begin..) – 无界序列,例如由 views::iota 返回的范围

范围库包括 范围算法,它们会急切地应用于范围,以及 范围适配器,它们会延迟地应用于视图。适配器可以组合成管道,以便它们的行动在迭代视图时发生。

定义在头文件 <ranges>
namespace std {

    namespace views = ranges::views;

}
(自 C++20 起)

命名空间别名 std::views 提供为 std::ranges::views 的简写。

定义在命名空间 std::ranges

内容

范围访问
定义在头文件 <ranges>
定义在头文件 <iterator>
返回指向范围开头的迭代器
(自定义点对象)[edit]
返回指示范围结束的哨兵
(自定义点对象)[edit]
返回指向只读范围开头的迭代器
(自定义点对象)[edit]
返回指示只读范围结束的哨兵
(自定义点对象)[edit]
返回指向范围的反向迭代器
(自定义点对象)[edit]
返回指向范围的反向结束迭代器
(自定义点对象)[edit]
返回指向只读范围的反向迭代器
(自定义点对象)[edit]
返回指向只读范围的反向结束迭代器
(自定义点对象)[edit]
返回等于范围大小的整数
(自定义点对象)[edit]
返回等于范围大小的有符号整数
(自定义点对象)[edit]
检查范围是否为空
(自定义点对象)[edit]
获取指向连续范围开头的指针
(自定义点对象)[edit]
获取指向只读连续范围开头的指针
(定制点对象)[编辑]
范围原语
定义在头文件 <ranges>
获取范围的迭代器和哨兵类型
(别名模板)[编辑]
获取范围的大小、差值和值类型
(别名模板)[编辑]
获取范围的引用类型
(别名模板)[编辑]
悬空迭代器处理
定义在头文件 <ranges>
一个占位符类型,指示不应该返回迭代器或 subrange,因为它们将是悬空的
(类) [编辑]
获取 borrowed_range 的迭代器类型或 subrange 类型
(别名模板)[编辑]
其他实用程序
定义在头文件 <ranges>
将范围标记为序列而不是单个值
(类模板) [编辑]
范围概念
定义在头文件 <ranges>
指定类型为范围,即它提供 begin 迭代器和 end 哨兵
(概念) [编辑]
指定类型为 range,并且从其表达式获得的迭代器可以安全地返回,而无需担心悬空
(概念) [编辑]
指定范围以恒定时间知道其大小
(概念) [编辑]
指定范围为视图,即它具有恒定时间复制/移动/赋值
(概念) [编辑]
指定其迭代器类型满足 input_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 output_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 forward_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 bidirectional_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 random_access_iterator 的范围
(概念) [编辑]
指定其迭代器类型满足 contiguous_iterator 的范围
(概念) [编辑]
指定范围具有相同的迭代器和哨兵类型
(概念) [编辑]
指定 range 能够安全地转换为 view 的要求
(概念) [编辑]
指定范围具有只读元素
(概念) [编辑]
范围转换
定义在头文件 <ranges>
从输入范围构造一个新的非视图对象
(函数模板) [编辑]
视图
定义在头文件 <ranges>
用于定义 view 的辅助类模板,使用 奇异递归模板模式
(类模板) [编辑]
将迭代器-哨兵对组合成 view
(类模板) [编辑]

[编辑] 范围工厂

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

[编辑] 范围适配器

定义在头文件 <ranges>
定义在命名空间 std::ranges
用于定义范围适配器闭包对象的辅助基类模板
(类模板) [编辑]
一个包含 range 中所有元素的 view
(别名模板) (范围适配器对象)[编辑]
其他 range 元素的 view
(类模板) [编辑]
一个拥有某个 range 的唯一所有权的 view
(类模板) [编辑]
一个 view,它将序列中的每个元素转换为右值
(类模板) (范围适配器对象)[编辑]
一个 view,它包含一个 range 中满足谓词的元素
(类模板) (范围适配器对象)[编辑]
一个 view,它对序列中的每个元素应用一个转换函数
(类模板) (范围适配器对象)[编辑]
一个 view,它由另一个 view 的前 N 个元素组成
(类模板) (范围适配器对象)[编辑]
一个 view,它由另一个 view 的初始元素组成,直到谓词返回 false 的第一个元素
(类模板) (范围适配器对象)[编辑]
一个 view,它由另一个 view 的元素组成,跳过前 N 个元素
(类模板) (范围适配器对象)[编辑]
一个 view,它由另一个 view 的元素组成,跳过初始元素子序列,直到谓词返回 false 的第一个元素
(类模板) (范围适配器对象)[编辑]
一个 view,它由通过扁平化 rangesview 获得的序列组成
(类模板) (范围适配器对象)[编辑]
一个 view,它由通过扁平化范围的视图获得的序列组成,并在元素之间使用分隔符
(类模板) (范围适配器对象)[编辑]
一个 view,它用于另一个 view 上使用分隔符分割获得的子范围
(类模板) (范围适配器对象)[编辑]
一个 view,它用于另一个 view 上使用分隔符分割获得的子范围
(类模板) (范围适配器对象)[编辑]
一个 view,它由适配的视图的串联组成
(类模板) (自定义点对象)[编辑]
从迭代器和计数创建一个子范围
(自定义点对象)[编辑]
将一个 view 转换为 common_range
(类模板) (范围适配器对象)[编辑]
一个 view,它以相反的顺序遍历另一个双向视图的元素
(类模板) (范围适配器对象)[编辑]
将一个 view 转换为 constant_range
(类模板) (范围适配器对象)[编辑]
它将一个 view,由 tuple-like 值组成,以及一个数字 N,并产生一个 view,它是每个元组的第 N 个元素
(类模板) (范围适配器对象)[编辑]
它将一个 view,由类似对的的值组成,并产生一个 view,它是每个对的第一个元素
(类模板) (范围适配器对象)[编辑]
它将一个 view,由类似对的的值组成,并产生一个 view,它是每个对的第二个元素
(类模板) (范围适配器对象)[编辑]
一个 view,它将适配序列的每个元素映射到元素位置和其值的元组
(类模板) (范围适配器对象)[编辑]
一个 view,它由对适配视图的相应元素的引用的元组组成
(类模板) (自定义点对象)[编辑]
一个 view,它由对适配视图的相应元素应用转换函数的结果组成
(类模板) (自定义点对象)[编辑]
一个 view,它由对适配视图的相邻元素的引用的元组组成
(类模板) (范围适配器对象)[编辑]
一个 view,它由对适配视图的相邻元素应用转换函数的结果组成
(类模板) (范围适配器对象)[编辑]
一个 views 范围,它们是另一个 view 的元素的 N 大小的非重叠连续块
(类模板) (范围适配器对象)[编辑]
一个 view,它的第 M 个元素是一个 view,它遍历另一个 view 的第 M 个到第 (M + N - 1) 个元素
(类模板) (范围适配器对象)[编辑]
view 分割为每个相邻元素对之间的子范围,其中给定的谓词返回 false
(类模板) (范围适配器对象)[编辑]
一个 view,它由另一个 view 的元素组成,每次前进 N 个元素
(类模板) (范围适配器对象)[编辑]
由适应后的视图的 n 元笛卡尔积计算出的结果元组组成的 视图
(类模板) (定制点对象)[编辑]

[编辑] 范围生成器

在头文件 <generator> 中定义
在命名空间 std 中定义
(C++23)
一个 视图,它表示同步 协程 生成器
(类模板) [编辑]

[编辑] 辅助项

[编辑] 范围适配器对象

参见 RangeAdaptorObject (RAO)。

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

参见 RangeAdaptorClosureObject (RACO)。

[编辑] 定制点对象

参见 定制点对象 (CPO)。

[编辑] 可赋值包装器

某些范围适配器使用 可复制盒子(直到 C++23)可移动盒子(自 C++23 起) 来包装它们​​的元素或函数对象。该包装器在需要时通过可赋值性增强包装的对象。

[编辑] 非传播缓存

某些范围适配器在说明性类模板 非传播缓存 的基础上进行定义,该类模板的行为类似于 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::constant_range<const R> &&
                  !ranges::constant_range<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”范围;否则,在不进行任何转换的情况下返回 r
2) /*as-const-pointer*/ 返回指向常量类型对象的指针。

[编辑] 范围适配器助手

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 作为左值转发。

[edit] 辅助概念

以下仅供说明的概念用于多种类型,但它们不是标准库接口的一部分。

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(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) (仅用于说明目的*)

[edit] 注释

功能测试 Std 特性
__cpp_lib_generator 202207L (C++23) std::generator – 用于范围的同步协程生成器
__cpp_lib_ranges 201911L (C++20) 范围库和 约束算法
202106L (C++20)
(DR)
不可 默认初始化视图
202110L (C++20)
(DR)
具有 所有权视图
202202L (C++23) ranges::range_adaptor_closure
202207L (C++23) 放宽 范围适配器 以允许使用仅移动类型
202211L (C++23) ranges::begin 等中删除“毒丸” (P2602) 重载
202302L (C++23) 放宽范围以允许某些投影
202406L (C++20)
(DR)
从间接可调用概念中删除公共引用要求
__cpp_lib_ranges_as_const 202207L (C++23) std::const_iteratorranges::as_const_view
__cpp_lib_ranges_as_rvalue 202207L (C++23) ranges::as_rvalue_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_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_zip 202110L (C++23) ranges::zip_view,
ranges::zip_transform_view,
ranges::adjacent_view,
ranges::adjacent_transform_view

[edit] 示例

#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

[edit] 缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。

DR 应用于 已发布的行为 正确的行为
LWG 3509
(P2281R1)
C++20 不清楚范围适配器对象如何绑定尾随参数 它们受
值约束
LWG 3948 C++23 possibly-const-rangeas-const-pointer 未声明为 noexcept 声明为 noexcept

[编辑] 另请参阅