“尺寸未实施”是什么意思?

2024-03-11

我写了以下代码:

use std::io::{IoResult, Writer};
use std::io::stdio;

fn main() {
    let h = |&: w: &mut Writer| -> IoResult<()> {
        writeln!(w, "foo")
    };
    let _ = h.handle(&mut stdio::stdout());
}

trait Handler<W> where W: Writer {
    fn handle(&self, &mut W) -> IoResult<()>;
}

impl<W, F> Handler<W> for F
where W: Writer, F: Fn(&mut W) -> IoResult<()> {
    fn handle(&self, w: &mut W) -> IoResult<()> { (*self)(w) }
}

进而rustc在我的终端中:

$ rustc writer_handler.rs
writer_handler.rs:8:15: 8:43 error: the trait `core::marker::Sized` is not implemented for the type `std::io::Writer`
writer_handler.rs:8     let _ = h.handle(&mut stdio::stdout());
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
writer_handler.rs:8:15: 8:43 error: the trait `core::marker::Sized` is not implemented for the type `std::io::Writer`
writer_handler.rs:8     let _ = h.handle(&mut stdio::stdout());
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

为什么是这样Writer需要实施Sized?在我看来Sized不需要。在保留的同时我应该做什么trait Handler有这个通用的论点吗?


在 Rust 1.0 中,类似的代码会产生相同的问题:

use std::io::{self, Write};

fn main() {
    handle(&mut io::stdout());
}

fn handle(w: &mut Write) -> io::Result<()> {
    handler(w)
}

fn handler<W>(w: &mut W) -> io::Result<()>
where
    W: Write,
{
    writeln!(w, "foo")
}

出现错误:

error[E0277]: the trait bound `std::io::Write: std::marker::Sized` is not satisfied
 --> src/main.rs:8:5
  |
8 |     handler(w)
  |     ^^^^^^^ `std::io::Write` does not have a constant size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `std::io::Write`
  = note: required by `handler`

Rust 的更高版本有错误

error[E0277]: the size for values of type `dyn std::io::Write` cannot be known at compilation time
  --> src/main.rs:8:13
   |
8  |     handler(w)
   |             ^ doesn't have a size known at compile-time
...
11 | fn handler<W>(w: &mut W) -> io::Result<()>
   |    ------- - required by this bound in `handler`
   |
   = help: the trait `std::marker::Sized` is not implemented for `dyn std::io::Write`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

The SizedTrait 相当特殊,非常特殊,以至于在大多数情况下它是类型参数的默认绑定。它表示在编译时具有已知固定大小的值,例如u8(1 个字节)或&u32(在具有 64 位指针的平台上为 8 个字节)等。这些值很灵活:它们可以放置在堆栈上并移动到堆上,并且通常按值传递,因为编译器知道它需要多少空间- 价值永远存在。

未调整大小的类型受到更多限制,并且类型的值Writer没有大小:它抽象地表示一些实现的未指定类型Writer,不知道实际类型是什么。由于实际类型未知,因此无法知道大小:一些大型类型是Writers,一些小类型是。Writer是特征对象的一个​​示例,目前它只能出现在指针后面的执行代码中。常见的例子包括&Writer, &mut Writer, or Box<Writer>.

这解释了为什么Sized是默认值:这通常是人们想要的。

无论如何,对于您的代码,这是弹出的,因为您正在使用handle with h,这是一个Fn(&mut Writer) -> IoResult<()>。如果我们将其与F: Fn(&mut W) -> IoResult<()>输入那个Handle实施是因为我们发现W = Writer,也就是说,我们正在尝试使用handle与特质对象&mut Writer, not a &mut W对于某些具体类型W。这是非法的,因为WTrait 和 impl 中的参数默认都有一个Sized绑定,如果我们手动覆盖它?Sized然后一切正常:

use std::io::{IoResult, Writer};
use std::io::stdio;

fn main() {
    let h = |&: w: &mut Writer| -> IoResult<()> {
        writeln!(w, "foo")
    };
    let _ = h.handle(&mut stdio::stdout());
}

trait Handler<W: ?Sized> where W: Writer {
    fn handle(&self, &mut W) -> IoResult<()>;
}

impl<W: ?Sized, F> Handler<W> for F
where W: Writer, F: Fn(&mut W) -> IoResult<()> {
    fn handle(&self, w: &mut W) -> IoResult<()> { (*self)(w) }
}

对于 Rust 1.0 代码:

use std::io::{self, Write};

fn main() {
    handle(&mut io::stdout());
}

fn handle(w: &mut Write) -> io::Result<()> {
    handler(w)
}

fn handler<W: ?Sized>(w: &mut W) -> io::Result<()>
where
    W: Write,
{
    writeln!(w, "foo")
}

我还写了一个博客文章关于Sized http://huonw.github.io/blog/2015/01/the-sized-trait/和一般特征对象,其中有更多细节。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

“尺寸未实施”是什么意思? 的相关文章

随机推荐