特质实施大小

时间:2015-07-20 11:58:08

标签: rust

我知道特征和切片是未分类的,即在编译时无法知道它们的大小,例如任何类型都可以实现特征,但该类型的大小可能不会。

然而,这个示例代码是否意味着实现特征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),并且可以从实现特定特征的任何其他类型转换为Bar (让我们将其命名为Foo)。

我通过引用而不是值传递Foo来解决它,但是我不确定编译器为什么要求实现者Sized所需要的。

2 个答案:

答案 0 :(得分:11)

为什么不起作用?

当你说每Foo都是Sized时,你就会把真相隐藏起来。是的,每个Foo都是Sized,但实际上每种类型在某些时候都有给定的大小。真正重要的信息是你没有说这个尺寸是多少。想象一下,如果Bar(i64)Foo,但Baz(i8)也是Foo(它们都是Sized,对吗?)您确定{{1} }} 成为?是8字节还是1字节长?编译器在尝试为您的函数Foo生成代码时会询问此问题。通常,from(foo: Foo)更像是使用语法Sized的“可能”式,表示在编译时类型大小可能是未知的。

如何解决?

通常你会抛弃?Sized部分,并使用以下语法,这实际上是一种C ++模板;当给定具有给定大小的具体类型时,它为编译器提供草图以编写实际代码。

: Sized

still error the fact that you cannot reimplement From because of the std crate基于read more here,但与原始问题无关。)

您还可以在函数的参数中使用引用特征对象trait Foo {} struct Bar(i64); impl Foo for Bar {} impl<F: Foo> From<F> for Bar { fn from(foo: F) -> Bar { Bar(64) } } 语法。这会将您的调用从静态调度转换为动态调度(this post),但您不能在此处执行此操作,因为签名是由特征强加的。

答案 1 :(得分:0)

Foo特征要求实施者为Sized。这并不意味着Foo本身会有一个大小。你误解了第二个代码示例的语法,因此我不确定你实际上要做什么。你在找这个吗?

impl From<i64> for Bar {
    fn from(val: i64) -> Bar {
        Bar(val)
    }
}

或者您想要一种从任何有符号整数构造Bar的方法吗?

我们这里有一个XY problem