此代码吸收了replace_with
的一些思想并将其扩展到结构,从而允许将函数应用到容器中,从而在出现紧急情况时对其进行清理。与在所有元素上运行replace_with
不同,不需要元素类型的默认值,只需容器类型。
我一辈子都做不好。如果我将TStruct
替换为Vec<T>
,并且在没有生命周期注释的情况下一切正常,那么只有当我尝试概括该函数时,我才会遇到生命周期问题。我需要在这里使用什么寿命才能满足借阅检查员的要求?
fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
f: impl Fn(T) -> T,
mut x: TStruct,
) -> TStruct
where
&mut TStruct: IntoIterator<Item = &mut T>,
&TStruct: IntoIterator<Item = &T>,
{
let x_ptr: *mut TStruct = &mut x;
for item_ref in &mut x {
let ptr: *mut T = item_ref;
unsafe {
let y1: T = std::ptr::read(ptr);
let fix_missing_elem = RunOnDrop {
f: || {
let y: TStruct = std::ptr::read(x_ptr);
let mut i = 0;
for item_ref in &y {
let current_item_ptr: *const T = item_ref;
if current_item_ptr == ptr {
break;
}
i += 1;
}
let mut j = 0;
for elem_ref in y {
if j == i {
std::mem::forget(elem_ref);
}
j += 1;
}
std::ptr::write(x_ptr, <TStruct as Default>::default());
},
};
let result = f(y1);
std::mem::forget(fix_missing_elem);
std::ptr::write(ptr, result);
}
}
x
}
struct RunOnDrop<F: FnMut()> {
f: F,
}
impl<'a, F: FnMut()> Drop for RunOnDrop<F> {
fn drop(&mut self) {
(self.f)()
}
}
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> src/lib.rs:6:5
|
6 | &mut TStruct: IntoIterator<Item = &mut T>,
| ^ explicit lifetime name needed here
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> src/lib.rs:6:39
|
6 | &mut TStruct: IntoIterator<Item = &mut T>,
| ^ explicit lifetime name needed here
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> src/lib.rs:7:5
|
7 | &TStruct: IntoIterator<Item = &T>,
| ^ explicit lifetime name needed here
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> src/lib.rs:7:35
|
7 | &TStruct: IntoIterator<Item = &T>,
| ^ explicit lifetime name needed here
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:1:1
|
1 | fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
| ^ - help: consider adding an explicit lifetime bound `T: 'static`...
| _|
| |
2 | | f: impl Fn(T) -> T,
3 | | mut x: TStruct,
4 | | ) -> TStruct
... |
41 | | x
42 | | }
| |_^
|
note: ...so that the reference type `&'static mut T` does not outlive the data it points at
--> src/lib.rs:1:1
|
1 | / fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
2 | | f: impl Fn(T) -> T,
3 | | mut x: TStruct,
4 | | ) -> TStruct
... |
41 | | x
42 | | }
| |_^
error[E0310]: the parameter type `TStruct` may not live long enough
--> src/lib.rs:1:1
|
1 | fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
| ^ -------- help: consider adding an explicit lifetime bound `TStruct: 'static`...
| _|
| |
2 | | f: impl Fn(T) -> T,
3 | | mut x: TStruct,
4 | | ) -> TStruct
... |
41 | | x
42 | | }
| |_^
|
note: ...so that the reference type `&'static mut TStruct` does not outlive the data it points at
--> src/lib.rs:1:1
|
1 | / fn inplace_map<T, TStruct: IntoIterator<Item = T> + Default>(
2 | | f: impl Fn(T) -> T,
3 | | mut x: TStruct,
4 | | ) -> TStruct
... |
41 | | x
42 | | }
| |_^