此代码工作正常(游乐场):
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>
。
解决方案是选择退出Sized
的T
:
struct Bar<T: ?Sized> {
v: Rc<T>,
}
以及实现的上下文:
impl<T: ?Sized> Bar<T>
where
T: Foo
?Sized
实际上不是约束,而是放松现有的Sized
约束,因此不需要。
选择 Sized
的结果是, Bar
的方法没有impl
块可以使用T
,但通过参考。