泛型
泛型函数
简单示例:
fn takes_anything<T>(x: T) {
// do something with x
}
fn takes_two_of_the_same_things<T>(x: T, y: T) {
// ...
}
fn takes_two_things<T, U>(x: T, y: U) {
// ...
}
例:
泛型结构体
struct Point<T> {
x: T,
y: T,
}
let int_origin = Point { x: 0, y: 0 };
let float_origin = Point { x: 0.0, y: 0.0 };
例:为泛型结构体实现方法。
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn swap(&mut self) {
std::mem::swap(&mut self.x, &mut self.y);
}
}
泛型约束
<T: Debug>
表示类型T需要实现Debug trait。<T: Debug + Clone>
表示类型T需要同时实现Debug trait与Clone trait。
where 从句
当泛型变量增多时,泛型的约束会让代码看起来很杂乱,使用where从句,可以让代码更加优美:
use std::fmt::Debug;
fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
// ...
}
可以写成:
use std::fmt::Debug;
fn foo<T, K>(x: T, y: K) where T: Clone , K: Clone + Debug {
// ...
}
按照官方文档的格式,以上代码可以写成:
use std::fmt::Debug;
fn foo<T, K>(x: T, y: K)
where T: Clone ,
K: Clone + Debug {
// ...
}
where甚至可以允许:
左侧可以是任意类型(在这里是i32),而不仅仅是一个类型参数(比如T)。
例:
trait ConvertTo<Output> {
fn convert(&self) -> Output;
}
impl ConvertTo<i64> for i32 {
fn convert(&self) -> i64 { *self as i64 }
}
// can be called with T == i32
fn normal<T: ConvertTo<i64>>(x: &T) -> i64 {
x.convert()
}
// can be called with T == i64
fn inverse<T>() -> T
// this is using ConvertTo as if it were "ConvertTo<i64>"
where i32: ConvertTo<T> {
42.convert()
}