2017-11-07 17 views
4

私は構造体オブジェクトのコレクションを持っています。私は、traitオブジェクトのイテレータを使ってコレクションを繰り返し処理したいのですが、適切なイテレータを作成することはできません。私の減少テストコードは次のとおりです。特性オブジェクトの参照の反復子として構造体のコレクションを反復処理する方法はありますか?

struct MyStruct {} 
struct MyStorage(Vec<MyStruct>); 

trait MyTrait {} // Dummy trait to demonstrate the problem 
impl MyTrait for MyStruct {} 

trait MyContainer { 
    fn items<'a>(&'a self) -> Box<Iterator<Item = &'a MyTrait> + 'a>; 
} 
impl MyContainer for MyStorage { 
    fn items<'a>(&'a self) -> Box<Iterator<Item = &'a MyTrait> + 'a> { 
     Box::new(self.0.iter()) 
    } 
} 

これは、次のコンパイラエラーを結果:

error[E0271]: type mismatch resolving `<std::slice::Iter<'_, MyStruct> as std::iter::Iterator>::Item == &MyTrait` 
    --> src/main.rs:12:9 
    | 
12 |   Box::new(self.0.iter()) 
    |   ^^^^^^^^^^^^^^^^^^^^^^^ expected struct `MyStruct`, found trait MyTrait 
    | 
    = note: expected type `&MyStruct` 
       found type `&MyTrait` 
    = note: required for the cast to the object type `std::iter::Iterator<Item=&MyTrait>` 

私の理解では、&MyStruct&MyTraitに正常に変換できるものの、標準ライブラリのIterator実装ができないことですこの場合はそれです。 同じ構成がVec<Box<MyStruct>>と​​で動作することに注意してください。ただし、ボクシングはここでは必要ないと感じます。

参照を使用してこの作業を行う方法はありますか?

+1

私は確認されませんでしたが、私はそれを試みたが、錆が(A」MyTrait +)& 'の間には差は見ない'と ' & 'a MyTrait'だから、もっと一般的な構文なので、おそらく2番目のものを使うべきです。 – trentcl

答えて

6

あなたはこのように、明示的に単一の要素をキャストする必要があります。

Box::new(self.0.iter().map(|e| e as &MyTrait)) 
+0

ありがとう、素敵な答え!ランタイム(cpu、mem)のコストがかかっているのでしょうか、それとも見た目のように「普遍的なキャスト」なのでしょうか? –

+5

特性オブジェクトの参照は、おそらく2つのポインタが大きい(オブジェクトに1つ、 "vtable"に1つ)ため、単純なポインタに比べてオーバーヘッドがありますが、計算は含まれません。パフォーマンスを向上させたい場合は、イテレータの周囲のボックスを削除する必要があります(特性に関連するタイプを使用する)。 – Stefan

関連する問題