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

C++23 ranges::to:范围转换函数 (P1206R7)

文章目录

    • 引言
    • C++23 Ranges 概述
    • `ranges::to` 的定义与功能
      • 定义
      • 功能
    • 使用场景
      • 范围转换为容器
      • 简化字符串解析
      • 映射转换为向量
    • `ranges::to` 的优势
      • 代码简洁性
      • 提高开发效率
      • 与C++23的stl容器的范围版本构造函数配合良好
    • 模板参数约束的思考
    • 总结

引言

在C++的发展历程中,每一个新版本都会带来一系列令人期待的新特性,C++23也不例外。其中,ranges::to 范围转换函数(P1206R7)的引入,为数据转换提供了更加便捷、高效的解决方案。本文将深入探讨 ranges::to 的定义、功能、使用场景以及其在实际编程中的优势。

C++23 Ranges 概述

在了解 ranges::to 之前,我们先来简单回顾一下C++23中Ranges的相关内容。C++23中,Ranges更新占比较大,主要包含两部分内容:一是修复已知问题,二是完善遗落组件,可看作是对C++20的收尾工作。

Ranges提供了一种抽象,允许C++程序对数据结构的元素进行统一操作,我们可以把它看作是对两个迭代器的泛化。最简单的范围应该定义了 begin()end() 元素。有几种不同类型的范围,如容器(containers)、视图(views)、大小范围(sized ranges)、假借范围(borrowed ranges)、双向范围(bidirectional ranges)、向前范围(forward ranges)等等。

ranges::to 的定义与功能

定义

ranges::to 是C++23引入的一个非常强大的功能,用于从范围构造对象(通常是容器)。其定义如下([range.utility.conv.to]):

template<class C, input_range R, class... Args> requires (!view<C>)constexpr C to(R&& r, Args&&... args);

需要注意的是,它仅限制模板参数 C 不是一个 view,也就是说,C 甚至可能不是一个 range。然而,它的实现用于 range_value_t<C> 获取 C 的元素类型,这使得 C 至少需要对 range 进行建模。

功能

ranges::to 的主要功能是将某个范围收集到某个对象中。它可以通过调用一个接受范围的构造函数、一个 std::from_range_t 标记的范围构造函数、一个接受迭代器 - 哨兵对的构造函数,或者通过将源范围的每个元素反向插入到参数构造的对象中来从源范围构造一个新的非视图对象。

使用场景

范围转换为容器

在C++20中,Ranges可以通过容器直接构造,而反过来却不行。例如:

auto view = std::views::iota(0, 10) | std::views::common;
// std::vector<int> vec { view }; // ERROR!
std::vector<int> vec { std::ranges::begin(view), std::ranges::end(view) }; // OK

而到了C++23,引入了 ranges::to,可以方便地进行上述转换:

// views to container
auto view = views::iota(0, 10);
std::vector<int> vec = view | ranges::to<std::vector>;

同样,容器与容器之间也可以直接转换:

std::list l { 1, 2, 3 };
std::vector<decltype(l)::value_type> v = l | ranges::to<std::vector>;

简化字符串解析

在解析简单分隔字符串时,ranges::to 也能发挥很大的作用。在C++20中,解析分隔字符串可能需要编写一些额外的代码:

const std::string& n = "1,2,3,4";
const std::string& delim = ",";
std::vector<std::string> line;
for (const auto& word : std::views::split(n, delim)) {line.push_back(std::string(word.begin(), word.end()));
}

随着C++23 ranges::to 的引入,这可以写成:

const std::string& n = "1,2,3,4";
const std::string& delim = ",";
const auto line = n | std::views::split(delim)| std::ranges::to<std::vector<std::string_view>>();

映射转换为向量

在C++23中,我们可以将 views::keysranges::to 结合起来,将映射转换为它的值类型的向量:

template<typename MapT>
auto mapToVec(const MapT &_map) {return _map | std::views::values | std::ranges::to<std::vector>();
}

ranges::to 的优势

代码简洁性

ranges::to 的出现,使得代码更加简洁明了。在以往的数据转换过程中,可能需要编写大量的代码来完成,而现在只需要使用 ranges::to 就可以轻松实现。例如,将范围转换为容器的操作,使用 ranges::to 可以减少不必要的代码,提高代码的可读性和可维护性。

提高开发效率

在实际编程中,我们常常需要将数据从一种形式转换为另一种形式,ranges::to 就像是为我们提供了一辆高效的运输车,大大提高了开发效率。它减少了开发者手动编写转换代码的工作量,让开发者可以将更多的精力放在业务逻辑的实现上。

与C++23的stl容器的范围版本构造函数配合良好

std::ranges::to 与C++23的stl容器的范围版本构造函数配合良好,使得数据转换更加流畅。它能够更好地适应C++23的新特性,为开发者提供了更加统一和高效的编程体验。

模板参数约束的思考

ranges::to 的定义中,对模板参数 C 的约束较为宽松,只限制其不是 view。论文的R3版本过去常常约束 Cinput_range,但在R4中这个约束被删除了。

ranges::to 的目标是将某个范围收集到某物中,但它不一定是实际范围,只是消耗所有元素的东西。例如,假设我们有一个范围 std::expected<int, std::exception_ptr>,称之为 results。我们可以将其收集到一个 std::vector<std::expected<int, std::exception_ptr>> 中,也可以将其收集到 std::expected<std::vector<int>, std::exception_ptr> 中:

auto processed = results | ranges::to<std::expected>();
if (not processed) {std::rethrow_exception(processed.error());
}std::vector<int> values = std::move(processed).value();
// go do more stuff

这种约束放松的好处在于,它支持了更多有趣的用例,并且不支持这些用例并不需要付出任何代价,我们只需要不要过早地拒绝它。

总结

C++23的 ranges::to 范围转换函数(P1206R7)为数据转换带来了极大的便利。它简化了代码,提高了开发效率,并且与C++23的stl容器的范围版本构造函数配合良好。同时,其对模板参数约束的设计也为更多有趣的用例提供了支持。随着C++23的逐渐普及,ranges::to 将会在实际编程中发挥越来越重要的作用。开发者可以充分利用这一特性,让自己的代码更加简洁、高效。

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

相关文章:

  • LeRobot 框架的核心架构概念和组件(中)
  • 深度学习中的查全率与查准率:如何实现有效权衡
  • CS4334立体声D/A转换器:为高品质音频设计提供低成本的解决方案
  • 音频分类的学习
  • css设置文字两端对齐text-align:justify不起作用的解决方法
  • HTML应用指南:利用POST请求获取全国圆通快递服务网点位置信息
  • ​​金融合规革命:​​R²AIN SUITE 如何重塑银行业务智能​
  • 入侵检测SNORT系统部署过程记录
  • 数据结构与算法-双向链表专题
  • Spring AI 集成 Mistral AI:构建高效多语言对话助手的实战指南
  • 毕业论文,如何区分研究内容和研究方法?
  • C#中的dynamic与var:看似相似却迥然不同
  • Ota++框架学习
  • 胶片转场视频剪辑思路
  • tocmat 启动怎么设置 jvm和gc
  • 大模型训练简介
  • 华硕服务器-品类介绍
  • RBTree的模拟实现
  • MySQL之基础事务
  • 常用的应用层网络协议对比
  • 从零玩转系列之 MCP AI Agent 理论+项目实战开发你的MCP Server
  • UOS专业版上通过源码安装 Python 3.13 并保留系统默认版本
  • 310. 最小高度树
  • 『 测试 』软件测试全流程与Bug管理核心要点解析
  • 2025年6月一区SCI-不实野燕麦优化算法Animated Oat Optimization-附Matlab免费代码
  • OpenEvidence AI临床决策支持工具平台研究报告
  • 零成本打造专属AI图像处理平台:IOPaint本地部署与远程访问指南
  • 数据库系统概论|第六章:关系数据理论—课程笔记2
  • 嵌入式学习笔记 - SystemCoreClock/1000000
  • 自然语言处理入门级项目——文本分类