当前位置: 首页 > ops >正文

C++23 views::zip 和 views::zip_transform (P2321R2) 深入解析

文章目录

    • 一、引言
    • 二、C++23与Ranges库背景知识
      • 2.1 C++23概述
      • 2.2 Ranges库回顾
    • 三、`views::zip` 详解
      • 3.1 功能与定义
      • 3.2 使用场景
      • 3.3 示例代码
    • 四、`views::zip_transform` 详解
      • 4.1 功能与定义
      • 4.2 使用场景
      • 4.3 示例代码
    • 五、`views::zip` 与 `views::zip_transform` 的对比
      • 5.1 功能差异
      • 5.2 使用场景差异
      • 5.3 代码复杂度差异
    • 六、总结

一、引言

在C++的发展历程中,每一个新版本都会带来一系列令人期待的新特性,这些特性不仅提升了语言的性能和表达能力,还为开发者提供了更加便捷和高效的编程方式。C++23作为C++标准的一个重要版本,引入了许多实用的特性,其中 views::zipviews::zip_transform (提案编号P2321R2)就是两个非常有价值的特性,它们与C++20引入的Ranges库紧密相关,为处理范围数据提供了新的视角和方法。

二、C++23与Ranges库背景知识

2.1 C++23概述

C++23是C++标准的下一个重要更新版本,虽然不如C++20那样具有颠覆性,但它依然带来了许多值得开发者关注的改进和新增特性。C++23在C++20的基础上进行了补充和优化,解决了一些细节问题,并引入了新的编程工具和方法,旨在进一步提升C++语言的功能和开发效率。

2.2 Ranges库回顾

C++20引入的Ranges库是一个重要特性,它彻底改变了我们处理序列数据的方式,提供了更富有表现力、更易组合的抽象。简单来说,Range就是一种可以遍历的序列,你可以把它想象成更智能、更灵活的数组或者容器。C++20引入了Ranges这个概念,让我们可以更方便地操作这些序列,例如,可以使用Ranges来过滤、转换、拼接序列等。

std::views 是C++20里提供的一系列工具函数,用来对序列进行各种变换。它可以帮助我们以一种非常直观的方式对序列进行操作,比如过滤、转换、切片等等。以下是一个简单的示例,展示了如何使用 std::views 来过滤出数组中的偶数,并将这些偶数加倍:

#include <iostream>
#include <vector>
#include <ranges>int main() {std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};auto result = numbers | std::views::filter([](int n) { return n % 2 == 0; })| std::views::transform([](int n) { return n * 2; });for (int n : result) {std::cout << n << ' ';}return 0;
}

在这个示例中,我们使用 std::views::filterstd::views::transform 对序列进行了处理,代码不仅简洁,而且非常直观。

三、views::zip 详解

3.1 功能与定义

std::ranges::views::zip 是C++23引入的一个范围适配器,它接受一个或多个 view ,并生成一个 view ,其第 i 个元素是由所有视图的第 i 个元素组成的类似元组的值。生成的视图的大小是所有适配的视图大小的最小值。

在标头 <ranges> 中定义如下:

template < ranges::input_range ... Views >
requires ( ranges::view < Views> && ...) && ( sizeof...(Views) > 0 )
class zip_view
: public ranges::view_interface <zip_view< Views...>>
(1) (C++23)namespace views {
inline constexpr /*unspecified*/ zip = /*unspecified*/;
}
(2) (自 C++23)调用签名
template < ranges::viewable_range... Rs >
requires /* 见下文 */
constexpr ranges::view auto zip( Rs&&... rs ) ;
(自 C++23)

zip_view 始终实现 input_range ,并且若所有适配的 view 类型均实现 forward_rangebidirectional_rangerandom_access_rangesized_range 时实现对应的概念。

3.2 使用场景

views::zip 适用于需要同时遍历多个范围的场景,例如,当你需要对多个数组或容器进行并行处理时,可以使用 views::zip 将它们组合在一起,然后进行统一的操作。

3.3 示例代码

#include <list>
#include <array>
#include <tuple>
#include <ranges>
#include <vector>
#include <string>
#include <iostream>void print(auto const rem, auto const& range)
{for (std::cout << rem; auto const& elem : range)std::cout << elem << ' ';std::cout << '\n';
}int main()
{auto x = std::vector{1, 2, 3, 4};auto y = std::list<std::string>{"α", "β", "γ", "δ", "ε"};auto z = std::array{'A', 'B', 'C', 'D', 'E', 'F'};print("Source views:", "");print("x: ", x);print("y: ", y);print("z: ", z);print("\nzip(x,y,z):", "");for (std::tuple<int&, std::string&, char&> elem : std::views::zip(x, y, z)){std::cout << std::get<0>(elem) << ' '<< std::get<1>(elem) << ' '<< std::get<2>(elem) << '\n';std::get<char&>(elem) += ('a' - 'A'); // modifies the element of z}print("\nAfter modification, z: ", z);
}

其运行的结果是:

Source views:
x: 1 2 3 4
y: α β γ δ ε
z: A B C D E Fzip(x,y,z):
1 α A
2 β B
3 γ C
4 δ DAfter modification, z: a b c d E F

四、views::zip_transform 详解

4.1 功能与定义

std::ranges::views::zip_transform 同样是C++23引入的一个范围适配器,它接受一个可调用对象和一个或多个 view ,并生成一个 view ,其第 i 个元素是将可调用对象应用于所有视图的第 i 个元素的结果。

在标头 <ranges> 中定义如下:

template< std::copy_constructible F, ranges::input_range... Views >
requires (ranges::view<Views> && ...) && (sizeof...(Views) > 0) &&std::is_object_v<F> && std::regular_invocable<F&, ranges::range_reference_t<Views>...> &&/*can-reference*/<std::invoke_result_t<F&, ranges::range_reference_t<Views>...>>
class zip_transform_view: public ranges::view_interface<zip_transform_view<F, Views...>>
(1) (since C++23)namespace views {inline constexpr /*unspecified*/ zip_transform = /*unspecified*/;
}
(2) (since C++23)Call signature
template< class F, ranges::viewable_range... Rs >
requires /* see below */
constexpr auto zip_transform( F&& f, Rs&&... rs );
(since C++23)

4.2 使用场景

views::zip_transform 适用于需要对多个范围的元素进行某种计算或转换的场景,例如,你可以使用它来计算两个数组对应元素的和、差、积等。

4.3 示例代码

#include <iostream>
#include <vector>
#include <ranges>int main() {std::vector<int> a = {1, 2, 3, 4};std::vector<int> b = {5, 6, 7, 8};auto result = std::views::zip_transform([](int x, int y) { return x + y; }, a, b);for (int val : result) {std::cout << val << ' ';}std::cout << '\n';return 0;
}

在这个示例中,我们使用 views::zip_transform 计算了两个向量对应元素的和,并将结果输出。

五、views::zipviews::zip_transform 的对比

5.1 功能差异

  • views::zip 主要用于将多个范围的元素组合成元组,方便同时遍历多个范围。它只是简单地将多个范围的元素打包在一起,不进行任何计算或转换。
  • views::zip_transform 则在 views::zip 的基础上,增加了对元素的计算或转换功能。它会将可调用对象应用于每个元组中的元素,并返回计算结果。

5.2 使用场景差异

  • 当你只需要同时遍历多个范围,而不需要对元素进行额外的计算时,使用 views::zip 即可。
  • 当你需要对多个范围的元素进行某种计算或转换时,使用 views::zip_transform 更加合适。

5.3 代码复杂度差异

  • views::zip 的代码相对简单,只需要将多个范围作为参数传递给 views::zip 即可。
  • views::zip_transform 除了需要传递多个范围外,还需要传递一个可调用对象,代码相对复杂一些。

六、总结

views::zipviews::zip_transform 是C++23中非常实用的两个特性,它们基于Ranges库,为处理多个范围的数据提供了更加便捷和高效的方式。views::zip 可以将多个范围的元素组合在一起,方便同时遍历;views::zip_transform 则可以对多个范围的元素进行计算或转换,进一步扩展了功能。

在实际开发中,我们可以根据具体的需求选择使用 views::zipviews::zip_transform 。同时,我们也可以将它们与其他Ranges库的工具函数结合使用,实现更加复杂的数据处理逻辑。随着C++23的不断普及和应用,这些新特性将逐渐得到更多的关注和使用,帮助开发者编写出更简洁、高效、易读的代码。

http://www.xdnf.cn/news/5850.html

相关文章:

  • 嵌入式开发中 C++ 跨平台开发经验与解决方案
  • DAY 24 元组和OS模块
  • 思极地图使用
  • 《算法导论(第4版)》阅读笔记:p39-p48
  • 基于STM32、HAL库的ADAU1701JSTZ音频接口芯片驱动程序设计
  • 【23种设计模式】模式背后运用的技术对照
  • 【Android】下拉刷新组件Swiperefreshlayout
  • 将 swagger 接口导入 apifox 查看及调试
  • android 权限配置
  • ThingsBoard(TODO)
  • 无人机失联保护模块技术解析!
  • 汽车工厂数字孪生实时监控技术从数据采集到三维驱动实现
  • 【神经网络与深度学习】通俗易懂的介绍非凸优化问题、梯度消失、梯度爆炸、模型的收敛、模型的发散
  • 【AI News | 20250513】每日AI进展
  • 贝叶斯优化Transformer融合支持向量机多变量时间序列预测,Matlab实现
  • 遨游卫星电话与普通手机有什么区别?
  • 【学习笔记】计算机操作系统(三)—— 处理机调度与死锁
  • 深入探讨 Java 性能术语与优化实践
  • TDengine 做为 Spark 数据源
  • 鸿蒙 PC 发布之后,想在技术上聊聊它的未来可能
  • 【redis】CacheAside的数据不一致性问题
  • 【Linux学习笔记】理解一切皆文件实现原理和文件缓冲区
  • MES管理系统构建智能制造时代下的全面质量管理体系
  • 半小时快速入门Spring AI:使用腾讯云编程助手CodeBuddy 开发简易聊天程序
  • 计算机视觉----时域频域在图像中的意义、傅里叶变换在图像中的应用、卷积核的频域解释
  • CSRF防范歪招
  • 互联网大厂Java求职面试:优惠券服务架构设计与AI增强实践-5
  • BlockMesh Ai项目 监控节点部署教程
  • 在 Linux 系统中过滤文件中的字符串
  • 尼康VR镜头防抖模式NORMAL和ACTIVE的区别(私人笔记)