2 回答

TA貢獻1829條經驗 獲得超13個贊
的Sized
特點是比較特殊的,如此特別,在大多數情況下,勢必對類型參數的默認值。它表示在編譯時已知固定大小的值,如u8
(1個字節)或&u32
(64位指針平臺上的8個字節)等。這些值很靈活:它們可以放在堆棧上并移到堆上并且通常按值傳遞,因為編譯器知道它需要多少空間。
未調整大小的類型受到更多限制,并且類型的值Writer
未調整大?。核橄蟮乇硎緦崿F的某些未指定類型,Writer
而不知道實際類型是什么。由于實際類型未知,因此無法知道大?。耗承┐笮褪?code>Writers,有些是小型。Writer
是特征對象的一個示例,此時,它只能出現在指針后面的已執行代碼中。常見的例子包括&Writer
,&mut Writer
或Box<Writer>
。
這解釋了為什么Sized
是默認值:它通常是人們想要的。
在任何情況下,對于你的代碼,這是因為你正在使用handle
而出現h
,這是一個Fn(&mut Writer) -> IoResult<()>
。如果我們將這與我們發現的F: Fn(&mut W) -> IoResult<()>
類型相匹配,那就是我們嘗試使用trait對象,而不是某種具體類型。這是非法的,因為trait和impl中的參數都默認為有一個綁定,如果我們手動覆蓋它然后一切正常:Handle
W = Writer
handle
&mut Writer
&mut W
W
W
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
和特征對象的博客文章,其中有一些細節。

TA貢獻1887條經驗 獲得超5個贊
首先,請注意這h
是一種實現的類型Fn(&mut Writer) -> IoResult<()>
。
h.handle
正被召喚; 這個要看的話,在Handler
這里實施W
是Writer
-注意的是仔細:W 是 Writer
,一個無膠式。該&mut stdio::stdout()
因此將被強制轉換為&mut Writer
特征的對象。這在理論上非常好,但是當被帶回實施時就會倒塌。當涉及到約束時,默認情況下它們是大小的,因此它會抱怨,Writer
您嘗試分配的值W
不是大小。
這里有兩個主要解決方案:
切換到使用具體的編寫器類型,
h
以便您處理大小的類型:use std::io::{IoResult, Writer, stdio, LineBufferedWriter};use std::io::stdio::StdWriter;fn main() { let h = |&: w: &mut LineBufferedWriter<StdWriter>| -> 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) }}
允許
W
成為未定義的類型。這是可以接受的,因為您只能通過引用使用它&mut W
。如果您希望將其用作裸型,例如W
按價值計算的方法,則不會這樣做。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) }}
我會建議支持一個unsized,W
即使你沒有在這種情況下使用它 - 沒有理由它需要大小。
添加回答
舉報