Rc、RefCell 和 Box 组合的新型模式

Newtype pattern of the combinations of Rc, RefCell and Box

因为我不想一遍又一遍地输入Rc::new(RefCell::new(Box::new(MyType::new(args...))))这样的代码, 我决定像下面这样创建新类型 RcRefBox

use std::rc::Rc;
use std::cell::RefCell;

struct RcRefBox<T>(Rc<RefCell<Box<T>>>);

impl<T> RcRefBox<T> {
    fn new(value: Box<T>) -> RcRefBox<T> {
        RcRefBox(Rc::new(RefCell::new(value)))
    }
}

trait Interface {}

struct A;
impl Interface for A {}

fn main() {
    let iface: RcRefBox<Interface> = RcRefBox::new(Box::new(A));
}

代码无法编译并出现以下错误: (围栏:http://is.gd/ITiR8Q

<anon>:19:16: 19:35 error: the trait `core::marker::Sized` is not implemented for the type `Interface` [E0277]
<anon>:19     let iface: RcRefBox<Interface> = RcRefBox::new(Box::new(A));
                         ^~~~~~~~~~~~~~~~~~~
<anon>:19:16: 19:35 note: `Interface` does not have a constant size known at compile-time
<anon>:19     let iface: RcRefBox<Interface> = RcRefBox::new(Box::new(A));
                     ^~~~~~~~~~~~~~~~~~~
<anon>:19:38: 19:51 error: the trait `core::marker::Sized` is not implemented for the type `Interface` [E0277]
<anon>:19     let iface: RcRefBox<Interface> = RcRefBox::new(Box::new(A));
                                               ^~~~~~~~~~~~~
<anon>:19:38: 19:51 note: `Interface` does not have a constant size known at compile-time
<anon>:19     let iface: RcRefBox<Interface> = RcRefBox::new(Box::new(A));
                                               ^~~~~~~~~~~~~
error: aborting due to 2 previous errors

如何修复这些错误?

问题不在于你的 struct 本身,而在于你通过的 trait

特征对象是动态大小的对象(不实现 Sized)。

通常,当您指定泛型类型的边界时(T 此处),您会限制它,但是当引入 Sized 时,决定应用它 作为默认边界 因为大多数通用代码处理 Sized 类型,结果 T 单独意味着 T: Sized.

有一个特殊的 "widening" 绑定说“T 可能不是 Sized”:?Sized,如果您希望能够,则必须申请拿走 trait 个物品。将其添加到您的代码中:

use std::rc::Rc;
use std::cell::RefCell;

struct RcRefBox<T: ?Sized>(Rc<RefCell<Box<T>>>);  // ?Sized

impl<T: ?Sized> RcRefBox<T> {                     // ?Sized
    fn new(value: Box<T>) -> RcRefBox<T> {
        RcRefBox(Rc::new(RefCell::new(value)))
    }
}

trait Interface {}

struct A;
impl Interface for A {}

fn main() {
    let iface: RcRefBox<Interface> = RcRefBox::new(Box::new(A));
}

让它工作 (http://is.gd/pSZKK2)。