我正在查看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}} }?
答案 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
的方法 - 编译器会自动为您插入引用操作。