泛型

泛型函数

简单示例:

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) {
    // ...
}

代表“这个函数带有一个泛型类型”,而x: T代表“x是T类型的”。

例:

泛型结构体

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()
}

results matching ""

    No results matching ""