Oth*_*ers 3 state rust borrow-checker
我已经编写了这个代码用于状态之间的转换,但是如果无法通过借用检查器:
struct State {
// ...
}
impl State {
fn next(self) -> (Self, u32) {
// ...
}
}
struct StateHolder {
state: State
}
impl StateHolder {
fn next_value(&mut self) -> u32 {
// ERROR: Cannot move out of borrowed context
let (new_state, byproduct) = self.state.next();
self.state = new_state;
return byproduct;
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎是我经常使用的那种情况std::mem::replace,但由于价值new_state取决于旧的状态,它在这里不起作用.
我知道我可以通过制作State工具Clone来完成这项工作:
fn next_value(&mut self) -> u32 {
let (new_state, byproduct) = self.state.clone().next();
self.state = new_state;
return byproduct;
}
Run Code Online (Sandbox Code Playgroud)
但我宁愿不做那样不必要的复制,也不要求State实施Clone.(我认为编译器会在这种情况下优化副本,但我不想依赖它.)
我也知道在不安全的Rust中有很多方法可以做到这一点,但对于这样一个简单且明显安全的模式来说,这似乎有些过分.
有没有办法在安全的Rust中写这个,没有不必要的复制?
最简单的方法:
fn next(&mut self) -> u32;
Run Code Online (Sandbox Code Playgroud)
我会诚实地说,消费和退货都感觉很奇怪self,而且这也是不切实际的.
如果你坚持fn next(self) -> (Self, u32)但愿意改变布局StateHolder,那就去吧state: Option<State>,因为Option有take:
let (new_state, byproduct) = self.state.take().unwrap().next();
self.state = Some(new_state);
byproduct
Run Code Online (Sandbox Code Playgroud)
如果你没有被困Option,或者使用它太痛苦,那么你确实可以使用std::mem::replace,但你需要一些State人这样做.如果State实现这很容易Default,但可能很昂贵:
let (new_state, byproduct) =
std::mem::replace(&mut self.state, State::default()).next();
std::mem::replace(&mut self.state, new_state);
byproduct
Run Code Online (Sandbox Code Playgroud)
最后,你确实可以打破unsafe将价值移出self.state......然而,如果计算在你填补它之前就会发生恐慌,那么你就打开了未定义行为之地的大门,这就是baaad.
| 归档时间: |
|
| 查看次数: |
68 次 |
| 最近记录: |