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
.
?Sized
is needed in the above example)
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.