Rust中的泛型Generics
泛型(Generics)是用于高效处理重复概念的工具,是具体类型或其他属性的抽象替代。
在Rust中,泛型是一种让函数、结构体、枚举、Trait等支持多种类型二不重复代码的机制;(类似于C++中的模板)Rust的泛型在编译期是单态化(monomorphization)的,即在编译时将泛型替换为具体的类型,不会带来运行期开销。
函数中的泛型
泛型函数是指,在函数签名中指定参数和返回值的类型的地方,改用泛型表示。
以查找切片中最大值为例(为保证元素可比较,需要约束为PartialOrd):
fn largest<T: std::cmp::PartialOrd>(list: &[T]) -> &T {let mut largest = &list[0];for item in list {if item > largest {largest = item;}}largest
}
const泛型
数组类型在 Rust 中写作 [T; N]
:
T
是元素类型(可以是泛型参数);N
是编译期常量长度(const
)。
同一类型不同长度的数组也是不同的数组类型。可以使用数组切片(引用)和泛型来解决处理任何类型数组的问题。
定义一个可以接受任意类型、任意长度的数组的函数:
fn print_array<T: std::fmt::Debug, const N: usize>(arr: [T; N]) {println!("{:?}", arr);
}
类型定义时的泛型
定义类型时,其数据不确定具体类型时,可用泛型替代。
结构体中的泛型
结构体中的字段类型用泛型来定义
pub struct Point<T, U> {x: T,y: U,
}
特化(Specialization)
泛型结构体中的方法也可类似C++中进行偏特化与全特化(不同的时,不同特化下方法不能重名);与C++传统特化(避免语义歧义)不同,Rust通过不同 <font style="color:rgb(0, 0, 0);">impl</font>
块实现类似效果:
impl<T: std::fmt::Debug, U: std::fmt::Debug> Point<T, U> {pub fn new(x: T, y: U) -> Self {Self { x, y }}pub fn full(&self) {println!("full: {:?}", self);}
}impl<T: std::fmt::Debug> Point<T, T> {pub fn partial(&self) {println!("partial: {:?}", self);}
}impl Point<i32, i32> {pub fn output(&self) {println!("none: {:?}", self);}
}
枚举中的泛型
枚举成员也可使用泛型,Rust中常用的Option与Result即为泛型枚举
enum Option<T> {Some(T),None,
}enum Result<T, E> {Ok(T),Err(E),
}
泛型约束
当需要泛型类型支持特定操作时,需要使用 trait 约束。例如,要打印泛型类型的值,需要它实现 <font style="color:rgba(0, 0, 0, 0.85);">Display</font>
内联约束
约束直接放在类型后面,当有多个时,使用+进行指定:
fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) {// ...
}
where语法
使用 <font style="color:rgba(0, 0, 0, 0.85);">where</font>
从句使约束更清晰:
fn some_function<T, U>(t: T, u: U)
whereT: Display + Clone,U: Clone + Debug,
{// ...
}