Vec <t>如何实现iter()?</t>

时间:2015-03-20 12:24:01

标签: rust

我正在查看Vec<T>的代码,看看它是如何实现iter()的,因为我想为我的struct实现迭代器:

pub struct Column<T> {
    name: String,
    vec: Vec<T>,
    ...
}

我的目标不是暴露字段并提供迭代器来为列执行循环,最大值,最小值,求和,平均值等。

fn test() {
    let col: Column<f32> = ...;
    let max = col.iter().max();
}

我想我会看到Vec<T>迭代的方式。我可以看到iter()中已SliceExt定义了[T],但Vec<T>已实现iter()而非Vec<T>,因此我很难理解如何从{{1}}拨打{{1}} }?

1 个答案:

答案 0 :(得分:11)

事实上,正如fjh所说,这是由于Rust中的解引用操作符函数以及如何解析方法而发生的。

Rust具有特殊的Deref特征,允许实现它的类型的值被解除引用&#34;获得另一种类型,通常是与源类型自然连接的类型。例如,像这样的实现:

impl<T> Deref for Vec<T> {
    type Target = [T];

    fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() }
}

表示将*一元运算符应用于Vec<T>会产生[T],您需要再次借用它:

let v: Vec<u32> = vec![0; 10];
let s: &[u32] = &*v;

(请注意,即使deref()返回引用,取消引用运算符*也会返回Target,而不是&Target - 如果您不借用,则编译器会插入自动取消引用立即取消引用值。)

这是第一块拼图。第二个是如何解决方法。基本上,当你写像

这样的东西
v.iter()

编译器首先尝试查找iter()类型上定义的v(在本例中为Vec<u32>)。如果找不到这样的方法,编译器会尝试插入适当数量的*&,以便方法调用生效。在这种情况下,它发现以下内容确实是一个有效的调用:

(&*v).iter()

请注意,Deref上的Vec<T>会返回&[T],并且切片上会定义iter()方法。这也是你可以调用的方式,例如对常规值采用&self的方法 - 编译器会自动为您插入引用操作。