范围库 (C++20)

来自cppreference.com
< cpp
 
 
 

范围库提供处理元素范围的组件,包括各种视图适配器。

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

    namespace views = ranges::views;

}
(C++20 起)

提供命名空间别名 std::views ,作为 std::ranges::views 的缩写。

定义于命名空间 std::ranges
范围访问
定义于头文件 <ranges>
定义于头文件 <iterator>
返回指向范围起始的迭代器
(定制点对象)
返回指示范围结尾的哨位
(定制点对象)
返回指向只读范围起始的迭代器
(定制点对象)
返回指示只读范围结尾的哨位
(定制点对象)
返回指向范围的逆向迭代器
(定制点对象)
返回指向范围的逆向尾迭代器
(定制点对象)
返回指向只读范围的逆向迭代器
(定制点对象)
返回指向只读范围的逆向尾迭代器
(定制点对象)
返回等于范围大小的整数
(定制点对象)
返回等于范围大小的有符号整数
(定制点对象)
检查范围是否为空
(定制点对象)
获得指向连续范围的起始的指针
(定制点对象)
获得指向只读连续范围的起始的指针
(定制点对象)
范围原语
定义于头文件 <ranges>
获得范围的关联类型
(别名模板)
悬垂迭代器处理
定义于头文件 <ranges>
占位类型,指示不应返回迭代器或子范围,因为它可能悬垂
(类)
获得塑造 borrowed_range 的迭代器类型或子范围类型
(别名模板)
范围概念
定义于头文件 <ranges>
指定类型为范围,即它同时提供 begin 迭代器和 end 哨位
(概念)
指定类型为 range 而且能安全返回从该类型表达式获得的迭代器而无悬垂之虞
(概念)
指定范围可在常数时间内知晓其大小
(概念)
指定范围为视图,即它拥有常数时间的复制/移动/赋值
(概念)
指定范围的迭代器类型满足 input_iterator
(概念)
指定范围的迭代器类型满足 output_iterator
(概念)
指定范围的迭代器类型满足 forward_iterator
(概念)
指定范围的迭代器类型满足 bidirectional_iterator
(概念)
指定范围的迭代器类型满足 random_access_iterator
(概念)
指定范围的迭代器类型满足 contiguous_iterator
(概念)
指定范围拥有相同的迭代器和哨位类型
(概念)
指定针对 range 的要求,令其可安全转换为 view
(概念)
视图
定义于头文件 <ranges>
用于定义 view 的辅助类模板,使用奇异递归模板模式
(类模板)
将迭代器/哨位对结合为一个 view
(类模板)

范围工厂

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

范围适配器

定义于头文件 <ranges>
定义于命名空间 std::ranges
包含 range 的所有元素的 view
(别名模板) (范围适配器对象)
某个其他 range 的元素的 view
(类模板)
拥有某 range 的独占所有权的 view
(类模板)
range 中满足某个谓词的元素构成的 view
(类模板) (范围适配器对象)
对序列的每个元素应用某个变换函数的 view
(类模板) (范围适配器对象)
由另一 view 的前 N 个元素组成的 view
(类模板) (范围适配器对象)
由另一 view 的到首个谓词返回 false 为止的起始元素组成的 view
(类模板) (范围适配器对象)
由另一 view 跳过首 N 个元素组成的 view
(类模板) (范围适配器对象)
由另一 view 跳过元素的起始序列,直至首个谓词返回 false 的元素组成的 view
(类模板) (范围适配器对象)
由拉平 rangeview 所获得的序列构成的 view
(类模板) (范围适配器对象)
用某个分隔符切割另一 view 所获得的子范围的 view
(类模板) (范围适配器对象)
用某个分隔符切割另一 view 所获得的子范围的 view
(类模板) (范围适配器对象)
从迭代器和计数创建子范围
(定制点对象)
转换 viewcommon_range
(类模板) (范围适配器对象)
以逆序迭代另一双向视图上的元素的 view
(类模板) (范围适配器对象)
选取元组式值组成的 view 和数值 N ,产生每个 tuple 的第 N 个元素的 view
(类模板) (范围适配器对象)
选取 pair 式值组成的 view 并产生每个 pair 的第一元素的 view
(类模板) (范围适配器对象)
选取 pair 式值组成的 view 并产生每个 pair 的第二元素的 view
(类模板) (范围适配器对象)
到被适配视图的对应元素的引用元组组成的 view
(类模板) (定制点对象)
由应用变换函数到被适配视图的对应元素的结果的元组组成的 view
(类模板) (定制点对象)
由到被适配视图的相邻元素的引用的元组组成的 view
(类模板) (范围适配器对象)
由应用变换函数到被适配视图的相邻元素的结果的元组组成的 view
(类模板) (范围适配器对象)

某些范围适配器用可复制包装包装其元素或函数对象。

范围适配器对象

范围适配器对象是接收 viewable_range 作为其首参数并返回 view 的定制点对象。一些范围适配器对象是一元的,即它们接收一个 viewable_range 作为其仅有的参数。其他范围适配器对象接收一个 viewable_range 和其他尾随参数。

若范围适配器接收多于一个参数,则它亦支持部分应用:令

  • a 为范围适配器对象,而
  • args... 为参数(通常适合作为尾随参数),

则表达式 a(args...) 拥有下列属性:

  • 它合法当且仅当对每个 args... 中的 e ,设 Edecltype((e))std::is_constructible_v<std::decay_t<E>, E>true
  • 当调用合法时,其结果对象对每个 e 中的 args... 存储以 std::forward<E>(e) 直接非列表初始化的 std::decay_t<E> 类型子对象,而且
  • 结果对象是范围适配器闭包对象(见后述)。

类似其他定制点对象,令

  • a 为任何范围适配器类型的 cv 无限定版本的对象,
  • args... 任何满足 aoperator() 的约束参数组,

的调用全部等价。

每个这些表达式的结果对象是一个 view 对象或范围适配器闭包对象。

注:范围适配器类型的 volatile 限定或 const-volatile 限定版本不支持 operator() 。数组和函数在绑定时转换成指针。

范围适配器闭包对象

范围适配器闭包对象是类型同下列对象之一(忽略 cv 限定)的对象:

  • 一元范围适配器对象、
  • 范围适配器对象绑定尾随参数的结果,及
  • operator| 连接两个范围适配器闭包对象的结果。

范围适配器对象接收一个 viewable_range 作为其仅有的参数并返回 view 。它们可通过管道运算符调用:若 C 是范围适配器闭包对象且 Rviewable_range ,则下列两个表达式等价(均为良构或非良构):

C(R)
R | C

此调用将绑定的参数(若存在)转发给关联的范围适配器对象。绑定的参数(若存在)被当作与 C 等同地为左值或右值以及具有 cv 限定。

两个范围适配器闭包对象能由 operator| 连接以产生另一个范围适配器闭包对象:若 CD 为范围适配器闭包对象,则 C | D 亦为范围适配器闭包对象,若它合法。

C | D 的绑定参数确定如下:

  • 对两个操作数中的每个作为绑定参数的子对象,结果对象中有一个同类型子对象(舍弃 cv 限定),
  • 这种绑定的参数以含有它的操作数中的源子对象直接非列表初始化,其中源被当作与操作数等同地为左值或右值以及具有 cv 限定,而且
  • 结果合法当且仅当所有绑定参数的初始化为合法。

结果的 operator() 的效果与合法性确定如下:给定 viewable_range R ,这两个表达式等价(均为合法或非合法):

R | C | D // (R | C) | D
R | (C | D)

注意:范围适配器闭包类型的 volatile 限定或 const-volatile 限定版本不支持 operator()

示例

#include <ranges>
#include <iostream>
 
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

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR 应用于 出版时的行为 正确行为
LWG 3509 C++20 不明确范围适配器对象如何绑定尾随参数 按值绑定它们