繁体   English   中英

rust:定义一个通用函数,该函数将接受对实现特定特征的任何可迭代事物的借用

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM