如何将Vec <Box <dyn Trait >>移到Vec <Rc <RefCell <dyn Trait >>>

时间:2020-05-23 17:47:43

标签: casting rust traits

我有一个Vec<Box<dyn Trait>>作为输入,我想将其元素存储在Vec<Rc<RefCell<dyn Trait>>>中。最好的方法是什么?

我尝试过:

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);
    }
}

但是我得到了错误:

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`

实际上有可能还是我需要更改输入类型?

2 个答案:

答案 0 :(得分:1)

尽管RefCell<dyn Trait>是有效的类型,但是由于RefCell<T>的声明允许T: ?Sized,所以目前似乎没有一种方法可以从模块外部创建一个{ {3}},这需要从大小值开始。

但是,您应该可以使用unsafe代码转换为CoerceUnsizedCell,因为两者都有#[repr(transparent)]

答案 1 :(得分:1)

如果您控制Trait,则一种选择是通过遵循内部实现,简单地为Box<dyn Trait>实现它:

// 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)));
    }
}

请注意,这会将已经Box的对象包装在第二个指针(Rc)后面,因此,如果您在对性能敏感的算法中使用dest,则必须取消引用它两次而不是一次。如果您能够重组代码以接受Box<T: Trait>,则可以通过将TBox移到RefCell中来消除双重间接。 / p>

相关问题