以下のような構造体を考えます。
#[derive(Debug)]
struct Parent {
name: String,
children: Vec<Child>,
}
#[derive(Debug)]
struct Child {
name: String,
}
impl Child {
fn update(&mut self, parent: &mut Parent) {
self.name = parent.name.clone();// 親の構造体のフィールドを可変参照する(可変参照する必要は無いが便宜上)
}
}
この構造体でupdate関連関数を呼び出すとき、自身を含むparentを引数に渡すときには注意が必要です。
まず実体にします。
let mut parent = Parent {
name: "parent".to_string(),
children: vec![Child {
name: "child".to_string(),
}],
};
ここで、以下のように自身を含む構造体をupdateに渡すと、可変参照が2回行われ所有権の規則に反します。
for child in &mut parent.children {
child.update(&mut parent);// cannot borrow `parent` as mutable more than once at a time
}
そのため、可変参照を2つ以上取らないようにするため、構造体から自身を退避した後に、戻す必要があります。
// std::mem::takeで奪うと、自身を含まなくなるので親を可変参照できる
let mut children = std::mem::take(&mut parent.children);
for child in &mut children {
child.update(&mut parent);
}
// 奪ったので戻す
parent.children = children;
最終的なコードは以下のようになります。
#[derive(Debug)]
struct Parent {
name: String,
children: Vec<Child>,
}
#[derive(Debug)]
struct Child {
name: String,
}
impl Child {
fn update(&mut self, parent: &mut Parent) {
self.name = parent.name.clone();
}
}
fn main() {
let mut parent = Parent {
name: "parent".to_string(),
children: vec![Child {
name: "child".to_string(),
}],
};
// std::mem::takeで奪うと、自身を含まなくなるので親を可変参照できる
let mut children = std::mem::take(&mut parent.children);
for child in &mut children {
child.update(&mut parent);
}
// 奪ったので戻す
parent.children = children;
println!("{:?}", parent);
}
これを実行するとParent { name: "parent", children: [Child { name: "parent" }] }
が結果になります。