什么“大小没有实现”是什么意思?

什么“大小没有实现”是什么意思?

我写了以下代码:


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`


慕少森
浏览 476回答 2
2回答

烙印99

的Sized特点是比较特殊的,如此特别,在大多数情况下,势必对类型参数的默认值。它表示在编译时已知固定大小的值,如u8(1个字节)或&u32(64位指针平台上的8个字节)等。这些值很灵活:它们可以放在堆栈上并移到堆上并且通常按值传递,因为编译器知道它需要多少空间。未调整大小的类型受到更多限制,并且类型的值Writer未调整大小:它抽象地表示实现的某些未指定类型,Writer而不知道实际类型是什么。由于实际类型未知,因此无法知道大小:某些大型是Writers,有些是小型。Writer是特征对象的一个示例,此时,它只能出现在指针后面的已执行代码中。常见的例子包括&Writer,&mut Writer或Box<Writer>。这解释了为什么Sized是默认值:它通常是人们想要的。在任何情况下,对于你的代码,这是因为你正在使用handle而出现h,这是一个Fn(&mut Writer) -> IoResult<()>。如果我们将这与我们发现的F: Fn(&mut W) -> IoResult<()>类型相匹配,那就是我们尝试使用trait对象,而不是某种具体类型。这是非法的,因为trait和impl中的参数都默认为有一个绑定,如果我们手动覆盖它然后一切正常:HandleW = Writerhandle&mut Writer&mut WWWSized?Sizeduse&nbsp;std::io::{IoResult,&nbsp;Writer};use&nbsp;std::io::stdio;fn&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;h&nbsp;=&nbsp;|&:&nbsp;w:&nbsp;&mut&nbsp;Writer|&nbsp;->&nbsp;IoResult<()>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeln!(w,&nbsp;"foo") &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;_&nbsp;=&nbsp;h.handle(&mut&nbsp;stdio::stdout());}trait&nbsp;Handler<W:&nbsp;?Sized>&nbsp;where&nbsp;W:&nbsp;Writer&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;handle(&self,&nbsp;&mut&nbsp;W)&nbsp;->&nbsp;IoResult<()>;}impl<W:&nbsp;?Sized,&nbsp;F>&nbsp;Handler<W>&nbsp;for&nbsp;F where&nbsp;W:&nbsp;Writer,&nbsp;F:&nbsp;Fn(&mut&nbsp;W)&nbsp;->&nbsp;IoResult<()>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;handle(&self,&nbsp;w:&nbsp;&mut&nbsp;W)&nbsp;->&nbsp;IoResult<()>&nbsp;{&nbsp;(*self)(w)&nbsp;}}而对于Rust 1.0代码:use&nbsp;std::io::{self,&nbsp;Write};fn&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;handle(&mut&nbsp;io::stdout());}fn&nbsp;handle(w:&nbsp;&mut&nbsp;Write)&nbsp;->&nbsp;io::Result<()>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;handler(w)}fn&nbsp;handler<W:&nbsp;?Sized>(w:&nbsp;&mut&nbsp;W)&nbsp;->&nbsp;io::Result<()>where &nbsp;&nbsp;&nbsp;&nbsp;W:&nbsp;Write,{ &nbsp;&nbsp;&nbsp;&nbsp;writeln!(w,&nbsp;"foo")}我还写了一篇关于Sized和特征对象的博客文章,其中有一些细节。

慕工程0101907

首先,请注意这h是一种实现的类型Fn(&mut Writer) -> IoResult<()>。h.handle正被召唤;&nbsp;这个要看的话,在Handler这里实施W是Writer-注意的是仔细:W&nbsp;是&nbsp;Writer,一个无胶式。该&mut stdio::stdout()因此将被强制转换为&mut Writer特征的对象。这在理论上非常好,但是当被带回实施时就会倒塌。当涉及到约束时,默认情况下它们是大小的,因此它会抱怨,Writer您尝试分配的值W不是大小。这里有两个主要解决方案:切换到使用具体的编写器类型,h以便您处理大小的类型:use&nbsp;std::io::{IoResult,&nbsp;Writer,&nbsp;stdio,&nbsp;LineBufferedWriter};use&nbsp;std::io::stdio::StdWriter;fn&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;h&nbsp;=&nbsp;|&:&nbsp;w:&nbsp;&mut&nbsp;LineBufferedWriter<StdWriter>|&nbsp;->&nbsp;IoResult<()>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeln!(w,&nbsp;"foo") &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;_&nbsp;=&nbsp;h.handle(&mut&nbsp;stdio::stdout());}trait&nbsp;Handler<W>&nbsp;where&nbsp;W:&nbsp;Writer&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;handle(&self,&nbsp;&mut&nbsp;W)&nbsp;->&nbsp;IoResult<()>;}impl<W,&nbsp;F>&nbsp;Handler<W>&nbsp;for&nbsp;F where&nbsp;W:&nbsp;Writer,&nbsp;F:&nbsp;Fn(&mut&nbsp;W)&nbsp;->&nbsp;IoResult<()>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;handle(&self,&nbsp;w:&nbsp;&mut&nbsp;W)&nbsp;->&nbsp;IoResult<()>&nbsp;{&nbsp;(*self)(w)&nbsp;}}允许W成为未定义的类型。这是可以接受的,因为您只能通过引用使用它&mut W。如果您希望将其用作裸型,例如W按价值计算的方法,则不会这样做。use&nbsp;std::io::{IoResult,&nbsp;Writer};use&nbsp;std::io::stdio;fn&nbsp;main()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;h&nbsp;=&nbsp;|&:&nbsp;w:&nbsp;&mut&nbsp;Writer|&nbsp;->&nbsp;IoResult<()>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeln!(w,&nbsp;"foo") &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;_&nbsp;=&nbsp;h.handle(&mut&nbsp;stdio::stdout());}trait&nbsp;Handler<W:&nbsp;?Sized>&nbsp;where&nbsp;W:&nbsp;Writer&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;handle(&self,&nbsp;&mut&nbsp;W)&nbsp;->&nbsp;IoResult<()>;}impl<W:&nbsp;?Sized,&nbsp;F>&nbsp;Handler<W>&nbsp;for&nbsp;F where&nbsp;W:&nbsp;Writer,&nbsp;F:&nbsp;Fn(&mut&nbsp;W)&nbsp;->&nbsp;IoResult<()>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;handle(&self,&nbsp;w:&nbsp;&mut&nbsp;W)&nbsp;->&nbsp;IoResult<()>&nbsp;{&nbsp;(*self)(w)&nbsp;}}我会建议支持一个unsized,W即使你没有在这种情况下使用它 - 没有理由它需要大小。
打开App,查看更多内容
随时随地看视频慕课网APP