RUST 每日一省:泛型约束——trait

news/2024/12/2 17:31:53/

        使用泛型编程时, 很多情况下的行为并不是针对所有类型都实现的,用trait作为泛型的约束。例如,我们编写一个判断两个变量大小的泛型函数,编译时,会运行如下错误。

fn max<T>(a: T, b: T) -> T {if a < b {b} else {a}
} fn main() {let m = max(1, 2);
}error[E0369]: binary operation `<` cannot be applied to type `T`--> src/main.rs:14:10|
14 |     if a < b {|        - ^ - T|        ||        T|
help: consider restricting type parameter `T`|
13 | fn max<T: std::cmp::PartialOrd>(a: T, b: T) -> T {|         ++++++++++++++++++++++

        这个编译错误是说, 由于泛型参数T没有任何约束——如果我们填入两个Struct类型,如何比较呢, 因此编译器认为a<b这个表达式是不合理的, 因为它只能作用于支持比较运算符的类型。编译器也进行了提示,只有impl了PartialOrd的类型, 才能支持比较运算符。修正如下。

fn max<T:PartialOrd>(a: T, b: T) -> T {if a < b {b} else {a}
} fn main() {let m = max(1, 2);}

trait约束语法

trait约束的语法如下:
fn generic<T: MyTrait + MyOtherTrait + SomeStandarTrait>(t: T)
{

        todo!()

}
 

        如果泛型参数有多个trait约束,通过+语法来指定多个trait约束;拥有多个泛型参数的函数,在函数名和参数列表之间会有很长的trait约束信息,使得函数签名可读性差。Rust提供where关键字来处理这种情况。代码如下,

fn max<T>(a: T, b: T) -> Twhere T: PartialOrd
{if a < b {b} else {a}
}

总结,泛型参数约束有两种语法:
(1) 在泛型参数声明的时候使用冒号: 指定;
(2) 使用where子句指定。

fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {}fn some_function<T, U>(t: T, u: U) -> i32
where T: Display + Clone,
U: Clone + Debug
{}

        在有了“泛型约束”之后, 编译器不仅会在声明泛型的地方做类型检查, 还会在调用的地方做类型检查。例如当用户调用时,编译器会分析泛型函数当场检查类型的合法性,此时泛型的类型检查就完成了。

fn max<T:PartialOrd>(a: T, b: T) -> T {if a < b {b} else {a}
} struct T1 {value: i32
}#[derive(PartialOrd,PartialEq)]
struct T2 {value: i32
}fn main() {let m = max(1, 2);let t11 = T1{value:1};let t12 = T1{value:1};let m = max(t11, t12);let t21 = T2{value:1};let t22 = T2{value:1};let m = max(t21, t22);}= help: the trait `PartialOrd` is not implemented for `T1`
note: required by a bound in `max`--> src/main.rs:31:10|
31 | fn max<T:PartialOrd>(a: T, b: T) -> T {|          ^^^^^^^^^^ required by this bound in `max`
help: consider annotating `T1` with `#[derive(PartialOrd)]`|
3  | #[derive(PartialOrd)]|

        我们看到定时泛型函数max时指定了PartialOrd,没有错误;但是在我们调用的时候,由于T1没有实现PartialOrd,导致调用失败了。


http://www.ppmy.cn/news/56086.html

相关文章

如果用上以下几种.NET EF Core性能调优,那么查询的性能会飙升

1、避免在循环中进行查询操作&#xff1a; 避免在循环中进行查询操作&#xff0c;可以将查询结果缓存到内存中&#xff0c;然后对内存中的数据进行操作&#xff0c;可以提高性能。这种方式适合集合数据量少的数据&#xff0c;否则利大于弊。 // 不建议的方式&#xff1a;在循…

测试开发备战秋招面试5-牛客刷题之链表篇

趁着5.1假期把牛客网的必刷的TOP101过一遍&#xff0c;额&#xff0c;题目量有点大&#xff0c;争取5天给刷完吧&#xff0c;哈哈&#xff0c;加油啦。再用雷布斯的那句话来激励自己吧&#xff1a;努力了那么多年,回头一望,几乎全是漫长的挫折和煎熬。对于大多数人的一生来说,顺…

d3.js学习笔记②搭建服务器(含报错解决)

强烈建议自己搭建一个服务器&#xff0c;否则在后续往js里导入本地数据&#xff08;比如csv、json文件等&#xff09;的时候会报错。我用的是Apache服务器&#xff0c;下载、安装过程参考这篇文章&#xff1a;Apache安装配置 在浏览器输入http://localhost/或者http://127.0.0…

Go语言测试——【单元测试 | Mock测试 | 基准测试】

作者&#xff1a;非妃是公主 专栏&#xff1a;《Golang》 博客主页&#xff1a;https://blog.csdn.net/myf_666 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录 序一、单元测试1. 测试文件命名2. 测试函数3.…

卡尔曼滤波器简介——多维卡尔曼滤波

原文&#xff1a;多维卡尔曼滤波 (kalmanfilter.net) 目录 前言 基本背景 状态外推方程 示例 - 飞机 - 无控制输入 示例 - 带控制输入的飞机 示例 – 坠落物体 状态外推方程维度 线性时不变系统 线性动态系统建模 状态外推方程的推导 状态空间表示形式 示例 - 等速…

PyQt5入门(一)——PyQt5与QtDesigner的安装

PyQt5与QtDesigner的安装 在Windows环境下安装在Ubuntu环境下安装测试 首先&#xff0c;需要确保你已经安装了Python和PIP&#xff0c;因为使用PIP来安装PyQt5是最简便的方法。以下是在Windows和Ubuntu环境下配置并安装PyQt5以及QtDesigner的步骤&#xff1a; 在Windows环境下…

3个经典线程同步问题

生产者消费者问题 问题描述 系统中有一组生产者进程和一组消费者进程&#xff0c;生产者进程每次生产一个产品放入缓冲区&#xff0c;消费者进程每次从缓冲区中取出一个产品并使用。生产者、消费者共享一个初始为空、大小为n的缓冲区 伪码描述 semaphore mutex 1;//互斥信…

浏览器点击下载太 LOW,如何提高下载操作的逼格?

文章目录 Part.I IntroductionChap.I 预备知识Chap.II URL Part.II 下载的方式Chap.I PythonChap.II WgetChap.III Curl Reference Part.I Introduction 用浏览器下载东西需要一个一个点击&#xff0c;当需要批量下载的时候&#xff0c;这样操作不免有些繁琐。本文整理了常用的…