【问题标题】:How to move a Vec<Box<dyn Trait>> Into Vec<Rc<RefCell<dyn Trait>>>如何将 Vec<Box<dyn Trait>> 移动到 Vec<Rc<RefCell<dyn Trait>>>
【发布时间】:2020-05-23 17:47:43
【问题描述】:

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

我试过了:

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`

是否真的可以或我需要更改输入类型?

【问题讨论】:

  • 问题不在于转换,而是RefCell 需要拥有它的数据,所以你根本无法构造RefCell&lt;dyn Trait&gt;。您需要将类型更改为 Vec&lt;Rc&lt;RefCell&lt;Box&lt;dyn Trait&gt;&gt;&gt;&gt;
  • 甚至Vec&lt;Box&lt;RefCell&lt;dyn Trait&gt;&gt;&gt;,我看到有转换Rc::from&lt;T&gt;(Box&lt;T&gt;)

标签: casting rust traits


【解决方案1】:

虽然RefCell&lt;dyn Trait&gt; 是一个有效类型,但由于RefCell&lt;T&gt; 的声明允许T: ?Sized,目前似乎没有一种方法可以从模块外部创建一个,除了CoerceUnsized,这需要启动具有大小的值。

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

【讨论】:

  • 好吧,你可以创建一个没有大小的强制,但这对 OP 没有帮助,因为它们以一个没有大小的值开始。
【解决方案2】:

如果您控制Trait,一种选择是通过推迟到内部实现来简单地为Box&lt;dyn Trait&gt; 实现它:

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

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

相关问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2021-12-04
    • 1970-01-01
    相关资源
    最近更新 更多