问题
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-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
- 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