2016-08-29 3 views
1

私はそれはBox<T>Tでこれを課していないとき、それはRngSizedを必要とする理由私は理解していないTが特性オブジェクトである場合、どのようにボックス<T>を作成しますか?

error[E0277]: the trait bound `rand::Rng: std::marker::Sized` is not satisfied 
    --> src/main.rs:16:21 
    | 
16 |   let mut r = Box::new(*rng); 
    |      ^^^^^^^^ `rand::Rng` does not have a constant size known at compile-time 
    | 
    = help: the trait `std::marker::Sized` is not implemented for `rand::Rng` 
    = note: required by `<std::boxed::Box<T>>::new` 

と文句を言い、次のコード

extern crate rand; 
use rand::Rng; 

pub struct Randomizer { 
    rand: Box<Rng>, 
} 

impl Randomizer { 
    fn new() -> Self { 
     let mut r = Box::new(rand::thread_rng()); // works 
     let mut cr = Randomizer { rand: r }; 
     cr 
    } 

    fn with_rng(rng: &Rng) -> Self { 
     let mut r = Box::new(*rng); // doesn't work 
     let mut cr = Randomizer { rand: r }; 
     cr 
    } 
} 

fn main() {} 

を持っています。

+1

これは実際には何の関係もありません。後でこれをメンバーに保存して、タイトルがかなり不正確になり、さらに検索者をあまり助けてくれることはありません。もし誰かがよりよいアイデアを考えていたら... –

+0

[trait objects](https://doc.rust-lang.org/book/trait-objects.html)について知っていますか? @MatthieuM。 – kennytm

+0

。あなたはタイトルが改善する必要があることは間違いありません。 – Andreas

答えて

4

より - それはあなたがそれをBox::newのプロトタイプに表示されていない理由は、すべての機能にimplicitly addedではなく、特殊な形質だ:ということ

fn new(x: T) -> Box<T> 

お知らせ値(または移動)でxが必要なので、関数を呼び出すことがどれだけ大きいかを知る必要があります。対照的に

Boxタイプ自体がSizedを必要としません。それが「バウンドデフォルトSizedのオプトアウト」を意味?Sizedをバインド(再び特別)形質を、使用しています。

pub struct Box<T> where T: ?Sized(_); 

あなたを介して見ると、無サイズタイプでBoxを作成するための一つの方法があります:

安全でないコードからは、生ポインタから作成することができます。それ以来、すべての正常なものが機能します。

3

問題は実際には非常に簡単です:あなたは形質オブジェクトを持っており、この特性オブジェクトについて知っている2つのだけのものがある:利用可能な方法の

  • そのリスト
  • そのデータへのポインタ
  • あなたは(ここでは、ヒープ上の)別のメモリ位置にこのオブジェクトを移動するために要求すると

、あなたは情報の1つの重要な部分が欠落していますそのサイズ

どのくらいのメモリを予約する必要がありますか?何ビット移動するのですか?

オブジェクトがSizedの場合、この情報はコンパイル時に認識されるため、コンパイラはそれを「注入」します。しかし、特性オブジェクトの場合、この情報は不明であり(残念ながら)、これは不可能である。

この情報を利用できるようにし、多形性のある移動/クローンを利用できるようにすることは非常に便利ですが、これはまだ存在せず、これまでの提案は何も思い出せず、 (メンテナンス、ランタイムペナルティの面で...)。 Sized特性および結合に関する

1

私はまた、答えを投稿したい。このような状況に対処するための1つの方法は

fn with_rng<TRand: Rng>(rng: &TRand) -> Self { 
    let r = Box::new(*rng); 
    Randomizer { rand: r } 
} 

錆の単相性は具体的な大きさの種類によってTRandを交換with_rngの必要な実装を作成しますされていること。さらに、TRandを必要とする形質の境界をSizedに追加することもできます。

関連する問題