特性实现大小 [英] Trait implementing Sized

查看:36
本文介绍了特性实现大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道特征和切片没有大小,即在编译时不可能知道它们的大小,例如任何类型都可以实现一个特征,但该类型可能没有大小.

I know that traits and slices are unsized, i.e. it's not possible to know their size at compile time, e.g. any type may implement a trait, but that type may not be sized.

然而,这个示例代码是不是意味着每个实现 trait Foo 的类型也需要实现 Sized ?

Nevertheless, doesn't this example code mean that every type which implements trait Foo needs to implement Sized too?

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`

我想为库的使用者提供一个类型(让我们将其命名为 Bar),并使其可以从任何其他实现了一个类型的类型转换为 Bar特定特征(让我们将其命名为 Foo).

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).

我通过引用而不是值传递 Foo 解决了这个问题,但我不确定编译器为什么会抱怨如果实现者需要 Sized.

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 时,你是在对自己隐瞒真相.是的,每个 Foo 都是 Sized 但实际上每种类型在某些时候都有给定的大小.真正重要的信息是你没有说这个尺寸是多少.想象一下,如果 Bar(i64)Foo,但 Baz(i8) 也是 Foo(它们是大小,对吗?)你确定 Foo 的大小是多少?它是 8 字节还是 1 字节长?编译器在尝试为您的函数 from(foo: Foo) 生成代码时会询问这个问题.通常,Sized 用在maybe"风格中,语法为 ?Sized,表示在编译时类型大小可能是未知的.

Why doesn't it work?

When you say that every Foo is Sized, you're kind of hiding the truth to yourself. Yes, every Foo is Sized but actually every type has a given size at some point. 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? Is it 8- or 1-byte long? This question is asked by the compiler when it tries to generate the code for your function 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 部分,而使用以下语法,这实际上是一种 C++ 模板;当给定具有给定大小的具体类型时,它为编译器提供了一个草图来编写实际代码.

Typically you ditch the : Sized part, and use the following syntax, which is actually kind of a C++ template; 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)
    }
}

(这将仍然错误基于您无法重新实现 From 因为 std crate 的事实,但它是与您原来的问题无关.)

(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.)

您还可以在函数的参数中使用引用特征对象 &Foo 语法.这会将您的调用从静态调度转换为动态调度(在此处阅读更多内容)但您不能在此处执行此操作,因为签名是由特征强加的.

You could also use the reference trait object &Foo syntax in the argument to your function. 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.

这篇关于特性实现大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆