2411rust,实现特征

原文

Rust2024中,impl Trait位置的默认工作方式有了变化.是为了简化impl Trait,以更好地匹配人们一般的需求.

还添加了一个灵活的语法,让你需要时可完全控制.

Rust2024开始,一直在更改,何时可在返回位置impl Trait隐藏类型中使用泛型参数的规则:

1,即对返回位置impl Trait隐藏类型,的新的默认值,可在域中用任意泛型参数,而不仅是(仅适合Rust2024)类型;
2,用来显式声明可用哪些类型一个语法(可在任意版本中使用).

新的显式语法"用约束":如,impl Trait+use<'x,T>表示允许隐藏类型使用'xT(但不能使用域内其他泛型参数).

背景:返回位置impl Trait

本篇涉及返回位置impl Trait,如以下示例:

fn process_data(data: &[Datum]
) -> impl Iterator<Item = ProcessedDatum> {data.iter().map(|datum| datum.process())
}

在此返回位置``使用->impl Iterator,表明该函数返回实际类型由编译器根据函数体确定的"某种迭代器".它叫做"隐藏类型",因为调用者无法确切地知道它是什么;

他们必须针对Iterator特征编码.但是,在生成代码时,编译器根据实际的精确类型生成代码,从而确保充分优化调用者.

尽管调用者不知道确切的类型,但确实需要知道它继续借用数据参数,这样可确保在迭代数据引用保持有效.

此外,调用者必须可无需查看函数体,仅根据类型签名来弄清楚它.

Rust当前规则是,返回位置impl Trait值只有在impl Trait自身中有引用的生命期时,才能使用引用.此例中,impl Iterator<Item = ProcessedDatum>引用生命期,因此抓数据非法的.

你可在玩耍地上亲眼看到它.

此时收到的错误消息(“隐藏类型抓生命期”)不是很直观,但它确实附带了如何修复它的有用建议:
帮助:要声明impl Iterator<Item = ProcessedDatum>
''_'时,你可添加显式''_'生命期约束

impl Iterator<Item = ProcessedDatum> + '_ {

此建议的显式版本,函数签名变为:

fn process_data<'d>(data: &'d [Datum]
) -> impl Iterator<Item = ProcessedDatum> + 'd {data.iter().map(|datum| datum.process())
}

在此版本中,在impl Trait类型中显式引用,'d数据的生命期,因此允许使用.即只要正在使用迭代器,就必须持续借用数据,即它(正确地)此例中标记错误:

let mut data: Vec<Datum> = vec![Datum::default()];
let iter = process_data(&data);
data.push(Datum::default()); //<-错误!
iter.next();

此设计的可用性问题

impl Trait中可用哪些泛型参数规则是在早期根据一组有限的示例确定的.随着时间,会注意到它们有许多问题.

1,不是正确的默认值

主要代码基(编译器和crates.io上的)的调查发现,绝大多数返回位置impl Trait值都要用生命期,因此默认不抓没用.

2,不够灵活

当前规则是返回位置impl Trait总是允许使用类型参数,有时如果它们出现在约束中,允许使用生命期参数.

如上,该默认值是错误的,因为大多数函数实际上确实想允许返回类型使用生命期参数:这至少有变通.
默认值也是错误的,因为某些函数想要显式声明它们不在返回类型使用类型参数,且现在无法覆盖它.

最初意图是类型别名impl Trait可解决该用例,但很麻烦.

3,难以解释

因为默认值错误的,所以用户经常遇见这些错误!添加编译器提示以建议+'_有用,但用户必须遵守不完全理解的提示并不是很好.

4,错误的建议

impl Trait添加+'_参数可能会很怪,但并不是很难.可惜,它一般是错误的注解,导致不必要的编译器错误,正确的修复很复杂,有时甚至不可能.考虑如下示例:

fn process<'c, T> {context: &'c Context,data: Vec<T>,
) -> impl Iterator<Item = ()> + 'c {data.into_iter().map(|datum| context.process(datum))
}

此处,处理函数用context.process来处理数据中的(T类型)每个元素.因为返回值使用环境,因此按+'c声明它.

在此真正目标是允许类型中,使用'c;写+'c实现该目标,因为现在在约束列表中有'c.但是,虽然编写+'c是使'c出现在约束中的方便方法,但也表明隐藏类型必须比'c更久.

该要求是不必要的,实际上会导致本例编译错误,在玩耍地上试一下.

5,与Rust的其他部分不一致

当前设计还与Rust其他部分不一致.

异步FN去糖

Rust定义异步fn来去糖返回->impl Future的普通fn.因此,你想像处理此函数:

async fn process(data: &Data) { .. }

…将(大致)去糖为:

fn process(data: &Data
) -> impl Future<Output = ()> {async move {..}
}

实际上,因为可用生命期的规则有问题,这不是实际的去糖.实际的去糖针对一个特殊的允许使用所有生命期impl Trait.

但是该形式的impl Trait并未向终端用户公开.

impl Trait中的特征

Rust2024设计

上述问题促使在Rust2024结合了两件事来用新的方法:

1,一个新的默认值,即返回位置impl Trait隐藏类型可用域中不仅是类型(仅适合Rust2024)的泛型参数;

2,一个显式声明可用哪些类型的语法.

新的显式语法"用约束":如,impl Trait+use<'x,T>表示允许隐藏类型使用'xT(但不能使用域内其他泛型参数).

现在默认可使用生命期

Rust2024中,默认是返回位置impl Trait值的隐藏类型使用域内无论是类型还是生命期泛型参数.

即在Rust2024中可很好编译这篇博文初始示例,设置玩耍地中的版本2024来试试:

fn process_data(data: &[Datum]
) -> impl Iterator<Item = ProcessedDatum> {data.iter().map(|datum| datum.process())
}

好!

impl Trait可包含一个use<>bound来精确指定使用的泛型类型和生命期

例外是,当函数仅接受读取值且不包含在返回值中的引用参数时.一个示例是下面的indices()函数:它接受一个&[T]类型的切片,但它唯一做的是读取长度,用它来创建一个迭代器.
返回值中不需要切片自身:

fn indices<'s, T>(slice: &'s [T],
) -> impl Iterator<Item = usize> {0 .. slice.len()
}

Rust2021中,该声明隐式地表示切片没有返回类型.但在Rust2024中,默认值恰恰相反.即像此调用者停止在Rust2024中编译,因为他们现在假设直到迭代完成,数据是借用的:

fn main() {let mut data = vec![1, 2, 3];let i = indices(&data);data.push(4); //<-错误!<--假设访问`'&data'`i.next(); //
}

这实际上可能就是你想要的!即你可稍后修改indices()的定义,这样它实际上在结果中包含切片.即,新的默认值延续了impl Trait的传统,即保留在不中断调用者时,函数更改其实现灵活性.

但是,如果它不是你想要的呢?如果想保证indices()不会在其返回值中,保存参数切片的引用,你现在在返回类型中包含use<>约束来显式表示返回类型中可包含哪些泛型参数来完成.

indices()时,返回类型实际上不使用泛型,因此最好写为use<>:

fn indices<'s, T>(slice: &'s [T],
) -> impl Iterator<Item = usize> + use<> {//-----返回类型不使用`''s'或'T'`0 .. slice.len()
}

这与早期版本中impl Trait的限制相应,它总是必须抓类型参数.此时,可如下,避免了编译错误,但仍比必要的更保守:

fn indices<T>(slice: &[T],
) -> impl Iterator<Item = usize> + use<T> {0 .. slice.len()
}

或:'静态约束.对完全不抓引用特例,也可用'静态绑定,如下(自己试一下):

fn indices<'s, T>(slice: &'s [T],
) -> impl Iterator<Item = usize> + 'static {//-------返回类型不会抓引用.0 .. slice.len()
}

"此时,静态约束很方便,特别是考虑到当前use<>约束的实现限制,但use<>约束总体上更灵活.

如,编译器有一个返回newtype索引I而不是usize索引的变量,因此它包含一个use<I>声明.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/477074.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习笔记|MaxKB对接本地大模型时,选择Ollma还是vLLM?

在使用MaxKB开源知识库问答系统的过程中&#xff0c;除了对接在线大模型&#xff0c;一些用户出于资源配置、长期使用成本、安全性等多方面考虑&#xff0c;还在积极尝试通过Ollama、vLLM等模型推理框架对接本地离线大模型。而在用户实践的过程中&#xff0c;经常会对候选的模型…

Python 快速入门(上篇)❖ Python基础知识

Python 基础知识 Python安装**运行第一个程序:基本数据类型算术运算符变量赋值操作符转义符获取用户输入综合案例:简单计算器实现Python安装** Linux安装: yum install python36 -y或者编译安装指定版本:https://www.python.org/downloads/source/ wget https://www.pyt…

【1.2 Getting Started--->Installation Guide】

NVIDIA TensorRT DOCS 此 NVIDIA TensorRT 10.6.0 安装指南提供安装要求、TensorRT 包中包含的内容列表以及安装 TensorRT 的分步说明。 安装指南 摘要&#xff1a; 本 NVIDIA TensorRT 10.3.0 安装指南提供了安装要求、TensorRT 软件包中包含的内容列表以及安装 TensorRT 的…

RT_Thread内核源码分析(三)——线程

目录 1. 线程结构 2. 线程创建 2.1 静态线程创建 2.2 动态线程创建 2.3 源码分析 2.4 线程内存结构 3. 线程状态 3.1 线程状态分类 3.2 就绪状态和运行态 3.3 阻塞/挂起状态 3.3.1 阻塞工况 3.4 关闭状态 3.4.1 线程关闭接口 3.4.2 静态线程关闭 3.4.3 动态线程关…

Unity图形学之CubeMap立方体贴图

1.CubeMap&#xff1a;有六个面的贴图组成 2. 假反射&#xff1a;反射天空盒子 &#xff08;1&#xff09;正常UV采样&#xff1a; &#xff08;2&#xff09;Cube的采样&#xff1a;利用反射角采样&#xff0c;反射角X和Cube的交点采样 Shader "Custom/TestReflect"…

C语言基础学习:抽象数据类型(ADT)

基础概念 抽象数据类型&#xff08;ADT&#xff09;是一种数据类型&#xff0c;它定义了一组数据以及可以在这组数据上执行的操作&#xff0c;但隐藏了数据的具体存储方式和实现细节。在C语言中&#xff0c;抽象数据类型&#xff08;ADT&#xff09;是一种非常重要的概念&…

Qt-多元素控件

Qt中的多元素控件 Qt提供的多元素控件有&#xff1a; 这里的多元素控件都是两两一对的。 xxWidget和xxView的一个比较简单的理解就是&#xff1a; xxView是更底层的实现&#xff0c; xxWidget是基于xxView封装来的。 可以说&#xff0c;xxView使用起来比较麻烦&#xff0c;但…

2023年9月GESPC++一级真题解析

一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 题号 123456789101112131415 答案 CDBCDBACACBBDDA 1. 我们通常说的 “ 内存 ” 属于计算机中的&#xff08;&#xff09;。 A. 输出设备 B. 输 ⼊ 设备 C. 存储设备 D. 打印设备 【答案】 C 【考纲知识点】…

wend看源码-APISJON

项目地址 腾讯APIJSON官方网站 定义 APIJSON 可以定义为一个面向HTTP 协议的JSON 规范&#xff0c;一个面向数据访问层的ORM 框架。其主要工作流程包括&#xff1a;前端按照既定格式组装 JSON 请求报文&#xff0c;通过 APIJSON-ORM 将这些报文直接转换为 SQL 语句&#xff0c…

VMware虚拟机Ubuntu桥接模式突然连接不上网络解决办法

在Linux环境进行开发时突然发现虚拟机中的Ubuntu突然连接不上网络&#xff0c;图形化界面也找不到有线连接选项。在此记录解决办法。 解决办法 1. 在终端命令行输入以下命令&#xff1a; sudo service network-manager stop2. 然后编辑以下文件将其中NetworkingEnable fals…

丹摩征文活动|摩智算平台深度解析:Faster R-CNN模型的训练与测试实战

目录 文章前言Faster R-CNN的简介Faster RCNN的训练与测试提前准备1.1 mobaxterm&#xff08;远程连接服务器&#xff09;1.2 本文的源码下载 目标检测模型 Faster-Rcnn2.1云服务器平台 数据上传内置JupyterLab的使用本地连接使用DAMODEL实例获取实例的SSH访问信息通过SSH连接通…

【数据结构】归并排序 —— 递归及非递归解决归并排序

归并排序 一、归并排序1、归并排序的思想2、归并排序代码实现&#xff08;递归&#xff09;<1> 归并排序的递归区间<2> 归并排序的稳定性<3> 拷贝 3、归并排序代码实现&#xff08;非递归&#xff09;<1> 循环区间溢出问题 二、总结 一、归并排序 1、…

调大Vscode资源管理器字体

对于调整资源管理器字体大小&#xff08;也就是下图红框&#xff09;&#xff0c;查找了网上很多方法。要么介绍的方法是调整了代码字体&#xff0c;要么是调节了终端字体&#xff0c;要么是通过整体放缩实现的调整&#xff0c;总之都不合适。 唯一的调整方法是在几篇CSDN里看到…

【Linux】-学习笔记04

第十二章、磁盘管理 1.查看磁盘空间使用量 1.1df命令 作用&#xff1a; 列出文件系统的磁盘空间占用情况 df&#xff0c;disk free&#xff0c;通过文件系统来快速获取空间大小的信息&#xff0c;当我们删除一个文件的时候&#xff0c;这个文件 不是马上就在文件系统当中消…

centos 服务器 docker 使用代理

宿主机使用代理 在宿主机的全局配置文件中添加代理信息 vim /etc/profile export http_proxyhttp://127.0.0.1:7897 export https_proxyhttp://127.0.0.1:7897 export no_proxy"localhost,127.0.0.1,::1,172.171.0.0" docker 命令使用代理 例如我想在使用使用 do…

Vue中Select选择器el-option实现动态多选

效果如图&#xff1a; 前端列表块显示部分&#xff1a; <el-table :data"tableData" border stripe :header-cell-class-name"headerBg" selection-change"handleSelectionChange"><el-table-column type"selection" width…

【ubuntu24.04.1最简洁安装方案】

我的电脑配置&#xff1a; 128GB固态硬盘&#xff0c;1TB 机械硬盘&#xff0c;我把整个 windows 系统全噶掉了&#xff0c;只安装ubuntu24.04.1一个Linux系统噶windows系统&#xff0c; 推荐使用 DiskGenius这个工具&#xff0c;好用&#xff0c;但是也要弄明白了再用啊&#…

k8s集群加入node节点为ubuntu 22.04

文章目录 1.环境准备1.1 关闭无用服务1.2 环境和网络1.3 apt源1.4 系统优化 2. 装containerd3. 接入k8s集群3.1 kubelet、kubeadm、kubectl安装3.2 缺少一个镜像3.3 接入k8s集群 4. 一些相关问题 1.环境准备 rootcto-gpu-pro-n01:~# lsb_release -a No LSB modules are availa…

C#桌面应用制作计算器进阶版01

基于C#桌面应用制作计算器做出了少量改动&#xff0c;其主要改动为新增加了一个label控件&#xff0c;使其每一步运算结果由label2展示出来&#xff0c;而当点击“”时&#xff0c;最终运算结果将由label1展示出来&#xff0c;此时label清空。 修改后运行效果 修改后全篇代码 …

如何构建高效的接口自动化测试框架?

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 在选择接口测试自动化框架时&#xff0c;需要根据团队的技术栈和项目需求来综合考虑。对于测试团队来说&#xff0c;使用Python相关的测试框架更为便捷。无论选…