问题
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
?Sizedis needed in the above example)
来源:https://stackoverflow.com/questions/61976226/how-to-move-a-vecboxdyn-trait-into-vecrcrefcelldyn-trait