C++ range

2023-05-16

C++20 引入了 range 来简化对元素序列的处理(可以省略掉许多的循环遍历)。

1. range 和 view

range

range concept 通过提供一个迭代器以及一个哨兵来表示一个元素范围,以允许对某个类型进行遍历。

template<class T>
concept range = requires(T& t) {
  ranges::begin(t);
  ranges::end(t);
};

如,vector 就是一个 range:

std::vector<int> vec{ 1, 2, 3 };

auto it1 = std::ranges::begin(vec);
auto it2 = std::ranges::end(vec);

view

view 是一个 range,且具有常数时间复杂度的的拷贝、移动和赋值操作(如,直接操作一对迭代器、或使用生成器来按需生成元素)。

template<class T>
concept view = ranges::range<T> && std::movable<T> && ranges::enable_view<T>;

template<class T>
inline constexpr bool enable_view =
    std::derived_from<T, view_base> || /*is-derived-from-view-interface*/<T>;

如,可通过 iota 来创建一个 view,类似于 Python 中的 range:

auto v1 = std::views::iota(1);		// [1, +inf)
auto v2 = std::views::iota(1, 10);	// [1, 10)

for (int i : v2)
{
    std::cout << i << ' ';
}

2. 范围工厂

会创建一个 view。

iota:创建一个不断递增的元素序列,可以是有界的,也可以是无界的。

#include <iostream>
#include <ranges>

int main()
{
	auto v1 = std::views::iota(10);		// [10, +inf)
	auto v2 = std::views::iota(1, 10);	 // [1, 10)

	for (int i = 0; i < 10; i++)
	{
		std::cout << v1[i] << ' ';
	}
	std::cout << '\n';

	for (int i : v2)
	{
		std::cout << i << ' ';
	}
}
10 11 12 13 14 15 16 17 18 19
1 2 3 4 5 6 7 8 9

istream_view:对某个输入流不断地应用 operator >>,从而获得一系列的元素。

#include <iostream>
#include <sstream>
#include <ranges>

int main()
{
	std::istringstream nums("1.1 2.2 3.3\t4.4\n5.5");
	auto v = std::ranges::istream_view<float>(nums);

	for (float f : v)
	{
		std::cout << f << ", ";
	}
}
1.1, 2.2, 3.3, 4.4, 5.5,

3. 范围适配器

接受一个 range,对其执行某些操作后,返回结果 view。

counted:从指定位置开始获取 n 个元素。

std::vector<int> vec{ 1, 2, 3, 4, 5, 6, 7 };

for (int i : std::views::counted(vec.begin() + 1, 3))
{
    std::cout << i << ' ';
}
2 3 4

drop:丢弃 range 中的前 n 个元素。

int nums[] = { 0, 1, 2, 3, 4, 5, 6 };

for (int i : std::views::drop(nums, 3))
{
    std::cout << i << ' ';
}
3 4 5 6

elements:获取第 n 列元素。

注:view 中的元素需要是 tuple-like 的。

std::vector<std::tuple<int, int, int>> vecs
{
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
};

for (int i : std::views::elements<1>(vecs))
{
    std::cout << i << ' ';
}
2 5 8

filter:对 range 进行过滤,只保留符合条件的元素。

int nums[] = { 0, 1, 2, 3, 4, 5 };
auto even = [](int i)
{
    return i % 2 == 0;
};

for (int i : std::views::filter(nums, even))
{
    std::cout << i << ' ';
}
0 2 4

join:合并多个 range。

std::vector<int> vec1{ 1, 2, 3 };
std::vector<int> vec2{ 4, 5, 6 };
std::vector<std::vector<int>> vecs{vec1, vec2};

for (int i : std::views::join(vecs))
{
    std::cout << i << ' ';
}
1 2 3 4 5 6

reverse:反转 range 中的元素。

const int a[] = { 1, 2, 3, 4, 5, 6, 7 };

for (int i : std::views::reverse(a))
{
    std::cout << i << ' ';
}
7 6 5 4 3 2 1

split:按指定的元素分割 range。

std::vector<int> vec{ 1, 2, 3, 4, 5, 6, 7 };

for (const auto& v : std::views::split(vec, 4))
{
    for (int i : v)
    {
        std::cout << i << ' ';
    }
    std::cout << '\n';
}
1 2 3
5 6 7

take:获取 range 中的前 n 个元素。

int nums[] = { 0, 1, 2, 3, 4, 5 };

for (int i : std::views::take(nums, 3))
{
    std::cout << i << ' ';
}
0 1 2

transform:对 range 中的每个元素执行指定的转换操作,转换操作的返回值就是结果 view 中的元素。

int nums[] = { 0, 1, 2, 3, 4, 5 };
auto square = [](int i)
{
    return i * i;
};

for (int i : std::views::transform(nums, square))
{
    std::cout << i << ' ';
}
0 1 4 9 16 25

4. 管道运算符

如果 C 是一个范围适配器闭包对象R 是一个可以转换为 view 的 range,则 C(R) 等价于 R | C

范围适配器闭包对象包括:一元范围适配器(只接受一个参数)、绑定了余下参数的多元范围适配器(只留下第一个参数未指定)和 R | C 的返回值。

int nums[] = { 0, 1, 2, 3, 4, 5 };

auto even = [](int i)
{
    return i % 2 == 0;
};

// 先过滤,然后反转过滤得到的元素
for (int i : nums | std::views::filter(even) | std::views::reverse)
{
    std::cout << i << ' ';
}
4 2 0

以下等价:

R | C | D 	// (R | C) | D
R | (C | D)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ range 的相关文章

  • 测试两个范围是否重叠的最有效方法是什么?

    给定两个包含范围 x1 x2 和 y1 y2 其中x1 x2 and y1 y2 测试两个范围是否重叠的最有效方法是什么 一个简单的实现如下 bool testOverlap int x1 int x2 int y1 int y2 retu
  • 使用C++11随机库生成随机数

    正如标题所示 我正在尝试找出一种使用新的 C 11 生成随机数的方法
  • Maven 依赖范围未按预期工作

    Maven 2 2 1 声称支持版本范围 参见例如http www sonatype com books mvnref book reference pom relationships sect project dependency htm
  • 如何查找两个范围内的共同日期

    我有 2 个日期范围 start date1 end date1 and start date2 end date2 是否有一种简单的 ruby 方法可以查找两个范围内的所有日期 您可以使用 start date1 end date1 to
  • 查找父节点所选文本的范围

    我想找到所选文本相对于父元素的范围 所以在这个 p 元素 即anchorOffset focusOffset 狐狸 是 16 19 p p The quick brown fox jumps over the lazy dog p 但如果我
  • 生成某个时间间隔内的时间戳范围并查询所有重叠事件

    我想在一个时间间隔内生成一系列时间戳范围 并在表中查询所有重叠事件 我是almost那里 但对 SQL 还很陌生 似乎无法克服这个困难 为了进行测试 我构建了一个包含一系列事件的表 每个事件都在某个日期时间范围内发生 CREATE TABL
  • Python range() 上的“in”运算符时间复杂度

    我有以下功能 def foo length num return num in range length 这个函数的时间复杂度是多少 注意到range 在Python 3上创建一个Range对象 这个函数的时间复杂度是O 1 还是O N 我
  • 有没有办法在 Swift 中立即生成一个填充一系列值的数组?

    在 python 中我可以生成一个值数组 Example arr range 0 30 有没有办法在 Swift 中立即生成一个填充一系列值的数组 您可以创建一个具有如下范围的数组 var values Array 0 100 这给你一个数
  • contenteditable 选择文本不起作用

    我面临以下问题 当我尝试在 a 中选择文本时contenteditable元素并且选择的结束是元素内容的开始 那么不会触发 select 事件 并且没有Selection and Range对象 有人可以就为什么会发生这种情况或如何防止这种
  • range() 不是每次都会计算它的参数吗?

    l作为参数传递给range其值在内部被修改的函数for循环 但循环是为了10次而不是5 i 0 l 10 for i in range l print i l l l 1 输出是 0 10 1 9 2 8 3 7 4 6 5 5 6 4 7
  • 流行指数超出范围[重复]

    这个问题在这里已经有答案了 N 8 f g 4 7 indexList range N print indexList print f g indexList pop f indexList pop g 在此代码中 我收到一个错误 指出 p
  • Java 有 IndexSet 和 Range 类吗?

    在 Objective C Cocoa 中 我们有NSIndexSet类 它通过保留范围数组来有效地存储一系列唯一索引 例如 集合 1 2 30 57 将存储为范围 1 30 和 57 而不是存储为 32 个数字的数组 这有助于以简单快速的
  • 将整个范围转换为大写而不循环遍历所有单元格

    现在我正在使用以下代码将股票代码列表从小写字母转换为大写字母 Dim Tickers As String Dim n As Integer For n 2 To Last Tickers UCase W Cells n 1 Value W
  • 从另一个范围中的值定义一个范围

    我有一个 Excel 文件 其中包含已完成或未完成的任务 并在列中用 是 或 否 表示 最终 我对不同列中的数据感兴趣 但我想设置代码 以便它忽略任务已完成的那些行 到目前为止 我已经定义了包含是 否的列范围 但我不知道在此范围上运行哪个命
  • postgres 中的 @> 运算符有什么作用?

    我在 postgres 中遇到了一个查询here http johanndutoit net searching in a radius using postgres 它使用 gt 地球物体上的操作员 我到处搜索过 但对这个运算符的含义一无
  • 突出显示/选择多个带有内容可编辑范围的 div?

    假设我有一套contenteditable true divs div div div div
  • Python:从区间到值的映射

    我正在重构一个函数 给定一系列隐式定义间隔的端点 检查间隔中是否包含数字 然后返回相应的值 不以任何可计算的方式相关 现在处理这项工作的代码是 if p lt 100 return 0 elif p gt 100 and p lt 300
  • 检查所选单元格是否在特定范围内

    我正在使用 C 创建 Excel 加载项 如何检查选定的 或代码中范围表示的单元格 是否在特定范围内 例如如何检查单元格 P 5 是否在 A 1 Z 10 范围内 Use Application Intersect 像这样 在VBA中 Su
  • 确定一个范围是否完全被一组范​​围覆盖

    如何检查范围是否为完全覆盖由一组范围 在以下示例中 WITH ranges id a b AS SELECT 1 0 40 UNION SELECT 2 40 60 UNION SELECT 3 80 100 UNION SELECT 4
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限

随机推荐

  • 原生PHP7操作mongodb4

    Mongodb安装篇 CentOS7 Mongodb4 0 1 https blog csdn net gaokcl article details 83587077 Mongodb 配置用户 https blog csdn net gao
  • Linux命令行卡住不显示命令的解决方法

    1 问题描述 在使用终端工具如Xshell iTerm2时登录到linux服务器后 xff0c 在运行某些程序出错时 xff0c 有的时候会出现命令行卡住不显示命令的情况 2 解决方案 在命令行中输入reset xff0c 再回车即可 xf
  • word文档转换为md文档

    1 xff0c 安装软件 官网 xff1a Pandoc Installing pandoc 2 xff0c 打开cmd xff0c 切换到word文件所在的目录 这个不会可以自行百度不难 3 xff0c 在根文件目录下输入如下这行代码 p
  • docker 的 --rm与docker rm 的区别

    Dockerfile里的VOLUME和docker run v path的时候挂载容器的挂载点效果是一致的 会在宿主机 var lib docker volumes目录生成随机目录 发现 rm不单单是删除掉容器 xff0c 还会删掉挂载点的
  • jenkins 面试题

    1 jenkins是什么 Jenkins是一个开源的 可扩展的持续集成 交付 部署 xff08 软件 代码的编译 打包 部署 xff09 的基于web界面的平台 允许持续集成和持续交付项目 xff0c 无论用的是什么平台 xff0c 可以处
  • ubuntu18.04安装llvm-9 clang-9

    低版本的ubuntu只能采用编译安装的方式 xff0c 高版本的ubuntu可以采用如下方式安装 span class token keyword echo span deb http apt llvm org xenial llvm to
  • linux 下conda环境的配置

    1 安装 anaconda 3 0 下载安装包 xff1a span class token function wget span https repo continuum io archive Anaconda3 5 0 0 Linux
  • Linux 下如何添加一个普通用户,并给予用户root权限

    1 添加用户 xff0c 首先用adduser命令添加一个普通用户 xff0c 命令如下 adduser test1 添加一个名为tommy的用户 span class token function passwd span test1 修改
  • 不使用密码向github提交代码

    每次向github提交代码时都要输入用户名密码 xff0c 太麻烦了 xff0c 影响效率 解决方法 xff1a 1 在命令行中输入 span class token function git span config global cred
  • centos7系统安装好后远程连接执行命令很卡

    centos7系统安装好后 xff0c 远程连接也ok 但远程连接之后执行命令很卡 xff0c 这个问题可能是macaddr导致的 xff0c 我们要检查一下macaddr是否和其他的服务器相同 MACADDR 61 其中 以AA BB C
  • UESTC 1170 红蓝点对

    UESTC 1170 是个变异的最近点对题目 xff0c 用分治策略和计算几何做的话好像会超因为时间上是1000ms xff0c 下面这个贪心做法是看了别人的博客知道的 处理红点到原点的距离然后根据距离排序 xff0c 蓝点一样 xff0c
  • CDH环境下HDFS权限问题

    CDH环境下Hadoop平台最高权限用户是hdfs xff0c 属于supergroup组 默认HDFS会开启权限认证 xff0c 所以操作时 xff0c 需要将root用户切换到hdfs用户 xff0c 否则会报错 问题 xff1a or
  • 手动开启/关闭HDFS的safemode(安全模式)

    在hadoop启动namenode的时候 xff0c 会启动安全模式 xff08 safemode xff09 xff0c 在该模式下 xff0c namenode会等待datanode向它发送块报告 xff08 block report
  • centos7 update gcc to 7.2

    centos7默认的gcc版本是4 8 xff0c 我们需要升级到7 2 安装gcc span class token function wget span https github com gcc mirror gcc archive r
  • centos7升级GLIBC后导致系统不能启动成功

    centos7 glibc2 13 glibc2 27 1 准备U盘系统盘 xff0c 系统要和原来的系统版本匹配 开机重启按F2进入BIOS xff0c 通过U盘启动系统 选择Rescue mode 2 接下来 xff0c 选择 Resc
  • 在Linux中如何运行C语言写的脚本

    目录 1 xff1a Linux下如何运行C语言脚本 2 xff1a 实例展示 1 xff1a Linux下如何运行C语言脚本 Linux别的系统我不知道是不是这个方法 xff0c 我是用的ubuntu的 xff0c 其他的我也没测试过 x
  • Linux——利用Shell脚本编写进度条

    初级版本 xff08 原始进度条 xff09 xff1a span class hljs shebang bin bash span span class hljs built in echo span span class hljs st
  • C语言的日期和时间函数的用法及相应示例

    1 xff0e 概念 在C C 43 43 中 xff0c 对字符串的操作有很多值得注意的问题 xff0c 同样 xff0c C C 43 43 对时间的操作也有许多值得大家注意的地方 下面主要介绍在C C 43 43 中时间和日期的使用方
  • xrdp完美实现Windows远程访问Ubuntu 16.04【包括多人桌面与原生桌面】

    多人桌面 1 安装xrdp sudo apt get install xrdp 2 安装vnc4server 我这里是安装xrdp的时候自动安装的 我看网上很多说是需要单独安装的 3 安装xfce4 sudo apt get install
  • C++ range

    C 43 43 20 引入了 range 来简化对元素序列的处理 xff08 可以省略掉许多的循环遍历 xff09 1 range 和 view range range concept 通过提供一个迭代器以及一个哨兵来表示一个元素范围 xf