How to move a Vec<Box<dyn Trait>> Into Vec<Rc<RefCell<dyn Trait>>>

浪子不回头ぞ 提交于 2021-02-20 10:39:12

问题


I have a Vec<Box<dyn Trait>> as input, and I want to store its elements in a Vec<Rc<RefCell<dyn Trait>>>. What is the best way to do it?

I tried with:

use std::cell::RefCell;
use std::rc::Rc;

trait Trait {}

fn main() {
    let mut source: Vec<Box<dyn Trait>> = Vec::new();
    let mut dest: Vec<Rc<RefCell<dyn Trait>>> = Vec::new();

    for s in source {
        let d = Rc::new(RefCell::new(s.as_ref()));
        dest.push(d);
    }
}

But I got the error:

error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied
  --> src/main.rs:12:19
   |
12 |         dest.push(d);
   |                   ^ the trait `Trait` is not implemented for `&dyn Trait`
   |
   = note: required for the cast to the object type `dyn Trait`

Is it actually possible or am I required to change the input type?


回答1:


Although RefCell<dyn Trait> is a valid type, since the declaration of RefCell<T> allows T: ?Sized, there does not currently appear to be a way to create one from outside the module, other than CoerceUnsized, which requires starting with a sized value.

However, you should be able to use unsafe code to convert to a Cell or UnsafeCell, since both have #[repr(transparent)].




回答2:


If you control Trait, one option is to simply implement it for Box<dyn Trait> by deferring to the inner implementation:

// We could implement Trait only for Box<dyn Trait>, but usually what you want
// is to implement it for all Boxes of things that are Trait instead
impl<T: ?Sized + Trait> Trait for Box<T> {}

fn pushes(dest: &mut Vec<Rc<RefCell<dyn Trait>>>, source: Vec<Box<dyn Trait>>) {
    for s in source {
        dest.push(Rc::new(RefCell::new(s)));
    }
}

Be aware this wraps the already-Boxed object behind a second pointer (Rc) so if you are using dest in a performance-sensitive algorithm it will have to dereference it twice rather than once. If you are able to restructure the code so you can accept Box<T: Trait>, you could eliminate the double indirection by moving the T out of the Box and into a RefCell.

Related questions

  • Why can't I push into a Vec of dyn Trait unless I use a temporary variable?
  • How do I pass Rc<RefCell<Box<MyStruct>>> to a function accepting Rc<RefCell<Box<dyn MyTrait>>>? (a similar case where the double indirection could be eliminated)
  • What does "Sized is not implemented" mean? (explains why ?Sized is needed in the above example)


来源:https://stackoverflow.com/questions/61976226/how-to-move-a-vecboxdyn-trait-into-vecrcrefcelldyn-trait

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!