[英]Trait implementing Sized
I know that traits and slices are unsized, ie it's not possible to know their size at compile time, eg any type may implement a trait, but that type may not be sized. 我知道特征和切片是未分类的,即在编译时不可能知道它们的大小,例如任何类型都可以实现特征,但是该类型可能没有大小。
Nevertheless, doesn't this example code mean that every type which implements trait Foo
needs to implement Sized
too? 不过,这个示例代码是不是意味着每个实现特性Foo
类型都需要实现Sized
呢?
trait Foo: Sized {}
struct Bar(i64);
impl Foo for Bar {}
If that's so, why doesn't this work? 如果是这样,为什么这不起作用?
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`
I want to provide to the consumer of the library a type (let's name it Bar
) and make it possible to convert to Bar
from any other type which implements a particular trait (let's name it Foo
). 我想向库的使用者提供一个类型(让我们将其命名为Bar
),并且可以从实现特定特征的任何其他类型转换为Bar
(让我们将其命名为Foo
)。
I solved it by passing Foo
by the reference instead of the value, but I'm not sure why the compiler complains if it's required for implementors to be Sized
. 我通过引用传递Foo
而不是值来解决它,但是我不确定为什么编译器会抱怨实现者需要Sized
。
When you say that every Foo
is Sized
, you're kind of hiding the truth to yourself. 当你说每个Foo
都是Sized
,你就是在向自己隐瞒真相。 Yes, every Foo
is Sized
but actually every type has a given size at some point. 是的,每个Foo
都是Sized
但实际上每种类型在某些时候都有给定的大小。 The real important information is that you're not saying how much this size is. 真正重要的信息是你没有说这个尺寸是多少。 Imagine if Bar(i64)
is Foo
, but Baz(i8)
is Foo
as well (they're both Sized
, right?) which size do you determine Foo
to be? 想象一下,如果Bar(i64)
是Foo
,但是Baz(i8)
也是Foo
(它们都是Sized
,对吗?)你确定Foo
大小是多少? Is it 8- or 1-byte long? 是8字节还是1字节长? This question is asked by the compiler when it tries to generate the code for your function from(foo: Foo)
. 当编译器尝试from(foo: Foo)
生成函数代码时,会询问此问题。 Usually, Sized
is rather used in a "maybe"-style with the syntax ?Sized
, indicating that the type size might be unknown at compile time. 通常, Sized
更适用于“可能”式的语法?Sized
,表示在编译时类型大小可能是未知的。
Typically you ditch the : Sized
part, and use the following syntax, which is actually kind of a C++ template; 通常你抛弃: Sized
部分,并使用以下语法,这实际上是一种C ++模板; it gives the compiler a sketch to write the actual code when given a concrete type with a given size. 当给定具有给定大小的具体类型时,它为编译器提供草图以编写实际代码。
trait Foo {}
struct Bar(i64);
impl Foo for Bar {}
impl<F: Foo> From<F> for Bar {
fn from(foo: F) -> Bar {
Bar(64)
}
}
(This will still error based on the fact that you cannot reimplement From
because of the std
crate , but it's not related to your original question.) (这将仍然错误基础上的事实,你不能重新实现From
因的std
箱 ,但它没有涉及到你原来的问题。)
You could also use the reference trait object &Foo
syntax in the argument to your function. 您还可以在函数的参数中使用引用特征对象&Foo
语法。 This would transform your call from static dispatch to dynamic dispatch ( read more here ) but you can't do this here because the signature is imposed by the trait. 这会将您的调用从静态调度转换为动态调度( 在此处阅读更多内容 ),但您不能在此处执行此操作,因为签名是由特征强加的。
The Foo
trait requires implementors to be Sized
. Foo
特性要求实现者的Sized
。 It doesn't mean that Foo
itself will have a size. 这并不意味着Foo
本身会有一个大小。 You're misunderstanding the syntax the second code example and I'm therefore not sure what you're actually trying to do. 你误解了第二个代码示例的语法,因此我不确定你实际上要做什么。 Are you looking for this? 你在找这个吗?
impl From<i64> for Bar {
fn from(val: i64) -> Bar {
Bar(val)
}
}
Or do you want a way to construct a Bar
from any signed integer? 或者你想要一种从任何有符号整数构造一个Bar
的方法?
We've got a XY problem here. 我们这里有一个XY问题 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.