[英]rust: Define a generic function that will accept a borrow to any iterable of things that implement a certain trait
我有一个特征和一个实现该特征的东西:
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 的可迭代对象。 IE
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.