2015-09-04 4 views
5

多くのライブラリでは、traitを実装するタイプを定義して、コールバックハンドラとして使用できます。これには、イベントを処理するために必要なすべてのデータを単一のデータ型でまとめて処理する必要があります。これは、借用を複雑にします。同時に複数の構造体フィールドを突き詰める最も速い方法は何ですか?

たとえば、mioは、を実装し、run the EventLoopのときに構造体を指定できます。これらの矮小データ型の例を考えてみましょう:

struct A { 
    pub b: Option<B> 
}; 

struct B; 

struct MyHandlerType { 
    pub map: BTreeMap<Token, A>, 
    pub pool: Pool<B> 
} 

あなたのハンドラは、タイプAの項目へTokenからマップを持っています。 Aタイプの各アイテムは、すでにBタイプの関連値を持っていてもいなくてもよい。ハンドラでは、TokenAの値を検索し、まだBの値がない場合は、ハンドラのPool<B>から1を取得します。この構成では

impl Handler for MyHandlerType { 
    fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>, 
      token: Token, events: EventSet) { 
     let a : &mut A = self.map.get_mut(token).unwrap(); 
     let b : B = a.b.take().or_else(|| self.pool.new()).unwrap(); 
     // Continue working with `a` and `b` 
     // ... 
    } 
} 

我々はself.poolにアクセスするために行くとき、それはself.mapself.poolが別個のエンティティであることを確認するために、直感的に可能だとしても、ボローチェッカーは(self.map経由)selfは既に借りていることを訴えます。

可能なアプローチの1つは、の各フィールドをOption<>にラップすることです。次に、メソッド呼び出しの開始時に、selfのうちtake()それらの値とは、コールの終了時にそれらを復元:

struct MyHandlerType { 
    // Wrap these fields in `Option` 
    pub map: Option<BTreeMap<Token, A>>, 
    pub pool: Option<Pool<B>> 
} 
// ... 

fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>, 
     token: Token, events: EventSet) { 
    // Move these values out of `self` 
    let map = self.map.take().unwrap(); 
    let pool = self.pool.take().unwrap(); 

    let a : &mut A = self.map.get_mut(token).unwrap(); 
    let b : B = a.b.take().or_else(|| self.pool.new()).unwrap(); 
    // Continue working with `a` and `b` 
    // ... 

    // Restore these values to `self` 
    self.map = Some(map); 
    self.pool = Some(pool); 
} 

これは動作しますが、少しのクルーゲ-yと感じています。また、メソッド呼び出しごとにselfに値を移動するオーバーヘッドを導入しています。

これを行うにはどうすればよいですか?

答えて

11

structの異なる部分に同時に変更可能な参照を取得するには、destructuringを使用します。例here

struct Pair { 
    x: Vec<u32>, 
    y: Vec<u32>, 
} 

impl Pair { 
    fn test(&mut self) -> usize { 
     let Pair{ ref mut x, ref mut y } = *self; 
     // Both references coexist now 
     return x.len() + y.len(); 
    } 
} 

fn main() { 
    let mut nums = Pair { 
     x: vec![1, 2, 3], 
     y: vec![4, 5, 6, 7], 
    }; 
    println!("{}", nums.test()); 
} 
+1

!!!ありがとうございました!私は非構造化について知っていましたが、それを使って変更可能な参照を同時に得ることはできませんでした。これは大きな助けとなりました! – zslayton

関連する問題