2015-07-20 129 views
6

我知道特徵和切片是未分級的,即不可能在編譯時知道它們的大小,例如,任何類型都可以實現特徵,但是這種類型可能沒有規模。實現尺寸的特徵

不過,這個例子代碼是不是表示實現特徵Foo的每個類型都需要執行Sized呢?

trait Foo : Sized {} 

struct Bar(i64); 

impl Foo for Bar {} 

如果是這樣,爲什麼不能正常工作?

impl From<Foo> for Bar { 
    fn from(foo: Foo) -> Bar { 
     Bar(64) 
    } 
} 
src\lib.rs:9:1: 15:2 error: the trait `core::marker::Sized` is not implemented for the type `Foo` [E0277] 
src\lib.rs:9 impl From<Foo> for Bar 
src\lib.rs:10 { 
src\lib.rs:11  fn from(foo: Foo) -> Bar { 
src\lib.rs:13   Bar(64) 
src\lib.rs:14  } 
       ... 
src\lib.rs:9:1: 15:2 note: `Foo` does not have a constant size known at compile-time 
src\lib.rs:9 impl From<Foo> for Bar 
src\lib.rs:10 { 
src\lib.rs:11  fn from(foo: Foo) -> Bar { 
src\lib.rs:13   Bar(64) 
src\lib.rs:14  } 

我想怎麼辦 - 提供對庫類型的消費者(允許其命名爲酒吧),並有可能轉換到從實現特定性狀的任何其他類型的酒吧(讓將其命名爲Foo)。

我實際上是通過將Foo傳遞給引用而不是值來解決它的,儘管我不完全確定爲什麼編譯器會抱怨,如果從實現者需要Sized。

回答

9

它爲什麼不起作用?

當你說每FooSized,你有點隱瞞自己的真相。是的,每個FooSized,但實際上每個類型在某個點上都有給定的大小。真正重要的信息是,你沒有說這個尺寸是多少。試想一下,如果Bar(i64)Foo,但是Baz(i8)也是Foo(它們都是Sized,對不對?)您確定Foo的尺寸是多少?是8位還是1位字節?編譯器在嘗試爲函數from(foo: Foo)生成代碼時,會詢問這個問題。通常,Sized相當於語法?Sized的「可能」風格,表示在編譯時類型大小可能未知。

如何解決?

通常你會丟棄: Sized部分,並使用下面的語法,它實際上是一種C++模板;當給定具有給定大小的具體類型時,它給編譯器一個草圖來寫實際的代碼。

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箱的,但它沒有涉及到你原來的問題會still error

你也可以在使用借&Foo語法你的功能的論點。這會將您的呼叫從靜態調度轉換爲動態調度(read more here),但特別是您無法在此執行此操作,因爲簽名是由特徵強加的。

0

Foo特性需要實現器的大小。這並不意味着Foo本身會有大小。你誤解了第二個代碼示例的語法,因此我不確定你實際要做什麼。你在找這個嗎?

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

或者你想要一種方法來從任何有符號整數構造一個Bar?

我們在這裏有一個XY problem