我有一个特质和一个实现该特质的东西:
trait HasPosition2D {
fn x(&self) -> &i32;
fn y(&self) -> &i32;
fn x_mut(&mut self) -> &mut i32;
fn y_mut(&mut self) -> &mut i32;
}
impl HasPosition2D for (i32,i32) {
fn x(&self) -> &i32 {&self.0}
fn y(&self) -> &i32 {&self.1}
fn x_mut(&mut self) -> &mut i32 {&mut self.0}
fn y_mut(&mut self) -> &mut i32 {&mut self.1}
}
我现在可以定义接受任何实现 HasPosition2D 的通用函数。例如
fn print(p: &impl HasPosition2D) {
println!("{} {}", p.x(), p.y());
}
我还定义了一个函数,它接受任何可以转换为 HasPosition2D 迭代的东西。即
fn print_all(ps: impl IntoIterator<Item=impl HasPosition2D>) {
for p in ps {
println!("{} {}", p.x(), p.y());
}
}
这允许我交换容器类型而无需更改代码。例如
let ps = vec![(42,42), (42,42)];
print_all(ps);
let ps = [(42,42), (42,42)];
print_all(ps);
不过,上面的函数移动了容器,我反而想借用。例如
//does not complile
fn print_all2(ps: &impl IntoIterator<Item=impl HasPosition2D>) {
for p in ps {
println!("{} {}", p.x(), p.y());
}
}
但这给出了错误:
error[E0277]: `&impl IntoIterator<Item = impl HasPosition2D>` is not an iterator
--> src\main.rs:35:14
|
35 | for p in ps {
| ^^ `&impl IntoIterator<Item = impl HasPosition2D>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `&impl IntoIterator<Item = impl HasPosition2D>`
= help: the trait `Iterator` is implemented for `&mut I`
= note: required because of the requirements on the impl of `IntoIterator` for `&impl IntoIterator<Item = impl HasPosition2D>`
我还想定义一个类似的函数来接受可变借用。
最后,如何为每个 impl 特征创建类型别名? (使用
#![feature(type_alias_impl_trait)]
和/或 #![feature(trait_alias)]
)
例如,对于非借用版本:
type HasPosition2DList = impl IntoIterator<Item=impl HasPosition2D>;
或
//does not compile
trait HasPosition2DList = IntoIterator<Item=impl HasPosition2D>;
我该怎么做?
into_iter
按值(而不是引用)获取 self
,因此如果您想避免移动,那么这并不能解决您的问题。 Vec
可以 deref
进入切片,所以我认为你想要更多类似这样的东西,以便接受任一类型作为参数:
fn print_all(ps: &[impl HasPosition2D]) {
for p in ps {
println!("{} {}", p.x(), p.y());
}
}
然后您可以按照示例中所示的方式调用它,只需添加
&
来借用:
fn main() {
let ps = vec![(42,42), (42,42)];
print_all(&ps);
let ps = [(42,42), (42,42)];
print_all(&ps);
}