问题描述
我正在使用两个独立的函数。
// This structure is not `Clone`.
struct MyStruct;
fn take_owned(s: MyStruct) -> MyStruct {
// Do things
s
}
fn take_mut(s: &mut MyStruct) {
*s = take_owned(s /* problem */);
}
use std::ptr;
// Temporarily turns a mutable reference into an owned value.
fn mut_to_owned<F>(val: &mut MyStruct,f: F)
where
F: FnOnce(MyStruct) -> MyStruct,{
// We're the only one able to access the data referenced by `val`.
// This operation simply takes ownership of the value.
let owned = unsafe { ptr::read(val) };
// Do things to the owned value.
let result = f(owned);
// Give the ownership of the value back to its original owner.
// From its point of view,nothing happened to the value because we have
// an exclusive reference.
unsafe { ptr::write(val,result) };
}
使用这个功能,我可以做到:
fn take_mut(s: &mut MyStruct) {
mut_to_owned(s,take_owned);
}
这段代码好听吗?如果没有,有没有办法安全地做到这一点?
解决方法
有人已经在名为 take_mut
的板条箱中实现了您正在寻找的东西。
函数take_mut::take
pub fn take<T,F>(mut_ref: &mut T,closure: F)
where
F: FnOnce(T) -> T,
允许使用 &mut T
指向的值,就好像它是拥有的一样,只要 T
之后可用。
...
如果闭包崩溃,将中止程序。
函数take_mut::take_or_recover
pub fn take_or_recover<T,F,R>(mut_ref: &mut T,recover: R,R: FnOnce() -> T,
允许使用 &mut T
指向的值,就好像它是拥有的一样,只要 T
之后可用。
...
如果 &mut T
恐慌,将用 recover
替换 closure
,然后继续恐慌。
实现本质上就是你所拥有的,加上所描述的恐慌处理。