多くのライブラリでは、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
タイプの関連値を持っていてもいなくてもよい。ハンドラでは、Token
のA
の値を検索し、まだ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.map
とself.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
に値を移動するオーバーヘッドを導入しています。
これを行うにはどうすればよいですか?
!!!ありがとうございました!私は非構造化について知っていましたが、それを使って変更可能な参照を同時に得ることはできませんでした。これは大きな助けとなりました! – zslayton