简体   繁体   中英

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

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?

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 orUnsafeCell , since both have #[repr(transparent)] .

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- Box ed 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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