6

多くのライブラリでは、指定された を実装する型を定義しtraitて、コールバック ハンドラとして使用できます。これには、イベントを処理するために必要なすべてのデータを 1 つのデータ型にまとめる必要があり、借用が複雑になります。

たとえば、を実行mioすると、構造体を実装Handlerして提供できます。これらの自明化されたデータ型の例を考えてみましょう:EventLoop

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

struct B;

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

ハンドラーには、Tokenタイプ のアイテム から へのマップがありますA。type の各アイテムには、 typeAの関連付けられた値がある場合とない場合がありますBAハンドラーで、指定された の値を検索し、まだ値Tokenがない場合Bは、ハンドラーの から値を取得しますPool<B>

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.mapこの配置では、とself.poolが別個のエンティティであることを直感的に確認できますが、 にアクセスすると、 が ( を介して)self既に借用されているとボロー チェッカーが文句を言います。self.mapself.pool

これに対する考えられるアプローチの 1 つは、各フィールドを でラップすることMyHandlerTypeですOption<>。次に、メソッド呼び出しの開始時に、take()これらの値を取り出しself、呼び出しの最後に復元します。

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);
}

これは機能しますが、少しおかしな感じがします。selfまた、メソッド呼び出しごとに値を出し入れするオーバーヘッドも発生します。

これを行う最善の方法は何ですか?

4

1 に答える 1

14

構造体のさまざまな部分への可変参照を同時に取得するには、分解を使用します。例はこちら

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());
}
于 2015-09-04T18:39:25.973 に答える