如何迭代结构集合作为特征对象引用的迭代器?

Zól*_*ván 5 polymorphism iterator rust

我有一个struct对象的集合.我想用特征对象的迭代器迭代集合,但是我不能为它创建一个合适的迭代器.我减少的测试代码是:

struct MyStruct {}
struct MyStorage(Vec<MyStruct>);

trait MyTrait {} // Dummy trait to demonstrate the problem
impl MyTrait for MyStruct {}

trait MyContainer {
    fn items<'a>(&'a self) -> Box<Iterator<Item = &'a MyTrait> + 'a>;
}
impl MyContainer for MyStorage {
    fn items<'a>(&'a self) -> Box<Iterator<Item = &'a MyTrait> + 'a> {
        Box::new(self.0.iter())
    }
}
Run Code Online (Sandbox Code Playgroud)

这会导致以下编译器错误:

error[E0271]: type mismatch resolving `<std::slice::Iter<'_, MyStruct> as std::iter::Iterator>::Item == &MyTrait`
  --> src/main.rs:12:9
   |
12 |         Box::new(self.0.iter())
   |         ^^^^^^^^^^^^^^^^^^^^^^^ expected struct `MyStruct`, found trait MyTrait
   |
   = note: expected type `&MyStruct`
              found type `&MyTrait`
   = note: required for the cast to the object type `std::iter::Iterator<Item=&MyTrait>`
Run Code Online (Sandbox Code Playgroud)

我的理解是,虽然&MyStruct通常可以转换为&MyTrait,Iterator但在这种情况下,标准库的实现不允许它.需要注意的是同一构造可与一Vec<Box<MyStruct>>Iterator<Item=&Box<MyTrait>>,但拳击并不觉得有必要在这里.

有没有办法让这个工作与参考?

Ste*_*fan 7

您需要显式地转换单个元素,如下所示:

Box::new(self.0.iter().map(|e| e as &MyTrait))
Run Code Online (Sandbox Code Playgroud)

  • 特征对象引用可能是两个大指针(一个指向对象,一个指向"vtable"),因此与简单指针相比有一些开销,但它不应涉及计算.虽然如果你想提高性能,你应该删除迭代器周围的Box(使用特征中的关联类型). (6认同)
  • 展望未来:不推荐使用没有显式“dyn”的特征对象,因此闭包应为“|e|” e 作为 MyTrait(&amp;dyn)` (2认同)