我知道 traits 和 slices 是没有大小的,即在编译时不可能知道它们的大小,例如任何类型都可以实现特征,但该类型可能无法确定大小。
然而,这个示例代码是否意味着每个实现特征 Foo
的类型也需要实现 Sized
?
trait Foo: Sized {}
struct Bar(i64);
impl Foo for Bar {}
如果是这样,为什么这行不通?
impl From<Foo> for Bar {
fn from(foo: Foo) -> Bar {
Bar(64)
}
}
error[E0277]: the trait bound `Foo + 'static: std::marker::Sized` is not satisfied
--> src/main.rs:7:6
|
7 | impl From<Foo> for Bar {
| ^^^^^^^^^ `Foo + 'static` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `Foo + 'static`
我想为库的使用者提供一个类型(我们将其命名为 Bar
),并可以从任何其他实现特定特征(我们将其命名为 Foo
)。
我通过引用而不是值传递 Foo
解决了这个问题,但我不确定如果实现者需要 Sized
编译器为什么会提示。
最佳答案
为什么不起作用?
当您说每个 Foo
都是 Sized
时,您是在隐瞒真相。是的,每个 Foo
都是 Sized
但实际上每个类型在某个时候都有给定的大小。真正重要的信息是你没有说这个尺寸是多少。想象一下,如果 Bar(i64)
是 Foo
,但是 Baz(i8)
也是 Foo
(它们是Sized
,对吗?)你确定 Foo
的大小是多少?它是 8 字节还是 1 字节长?编译器在尝试为您的函数 from(foo: Foo)
生成代码时会询问此问题。通常,Sized
以“可能”的形式使用,语法为 ?Sized
,表明类型大小在编译时可能是未知的。
如何解决?
通常您会放弃 : Sized
部分,并使用以下语法,这实际上是一种 C++ 模板;当给定具有给定大小的具体类型时,它为编译器提供了编写实际代码的草图。
trait Foo {}
struct Bar(i64);
impl Foo for Bar {}
impl<F: Foo> From<F> for Bar {
fn from(foo: F) -> Bar {
Bar(64)
}
}
(这将 still error 基于 the fact that you cannot reimplement From
because of the std
crate ,但它与您的原始问题无关。)
您还可以在函数的参数中使用引用特征对象 &Foo
语法。这会将您的调用从静态分派(dispatch)转换为动态分派(dispatch) (read more here),但您不能在此处执行此操作,因为签名是由特征强加的。
关于rust - 特征实现大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31515921/