为什么构建器函数需要大小特征才能生成 Rc<T>?



此代码工作正常(游乐场):

use std::rc::Rc;
trait Foo {
    fn foo(&self);
}
struct Bar<T> {
    v: Rc<T>,
}
impl<T> Bar<T> where
T: Foo {
    fn new(rhs: Rc<T>) -> Bar<T> {
        Bar{v: rhs}
    }
}
struct Zzz {
}
impl Zzz {
    fn new() -> Zzz {
        Zzz{}
    }
}
impl Foo for Zzz {
    fn foo(&self) {
        println!("Zzz foo");
    }
}
fn make_foo() -> Rc<Foo> {
    Rc::new(Zzz{})
}
fn main() {
    let a = Bar::new(Rc::new(Zzz::new()));
    a.v.as_ref().foo()
}

但是,如果我制作包装器以生成RC,则编译器会抱怨缺少大小的性状(游乐场)

fn make_foo() -> Rc<dyn Foo> {
    Rc::new(Zzz::new())
}
fn main() {
    let a = Bar::new(make_foo());
    a.v.as_ref().foo()
}

在这两种情况下

默认情况下,所有类型变量都假定为 Sized。例如,在Bar struct的定义中,有一个隐式的Sized约束,因此:

struct Bar<T: Sized> {
    v: Rc<T>,
}

对象dyn Foo 不能为Sized,因为Foo的每个可能实现都可能具有不同的大小,因此没有一个大小可以选择。但是您正在尝试实例化Bar<dyn Foo>

解决方案是选择退出SizedT

struct Bar<T: ?Sized> {
    v: Rc<T>,
}

以及实现的上下文:

impl<T: ?Sized> Bar<T>
where 
    T: Foo 

?Sized实际上不是约束,而是放松现有的Sized约束,因此不需要。

选择 Sized的结果是, Bar的方法没有impl块可以使用T,但通过参考。

相关内容

  • 没有找到相关文章

最新更新