范围库 (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 不明确范围适配器对象如何绑定尾随参数 按值绑定它们