Bar*_*ton 4 iterator mutable rust
尝试在安全的 Rust 中创建可变迭代器时,我遇到了生命周期问题。
这是我将问题简化为:
struct DataStruct<T> {
inner: Box<[T]>,
}
pub struct IterMut<'a, T> {
obj: &'a mut DataStruct<T>,
cursor: usize,
}
impl<T> DataStruct<T> {
fn iter_mut(&mut self) -> IterMut<T> {
IterMut { obj: self, cursor: 0 }
}
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let i = f(self.cursor);
self.cursor += 1;
self.obj.inner.get_mut(i)
}
}
fn f(i: usize) -> usize {
// some permutation of i
}
Run Code Online (Sandbox Code Playgroud)
my 的结构DataStruct永远不会改变,但我需要能够改变其中存储的元素的内容。例如,
let mut ds = DataStruct{ inner: vec![1,2,3].into_boxed_slice() };
for x in ds {
*x += 1;
}
Run Code Online (Sandbox Code Playgroud)
编译器给我一个关于我试图返回的引用的生命周期冲突的错误。它发现我不期望的生命周期是next(&mut self)函数的范围。
如果我尝试在 上注释生命周期next(),那么编译器会告诉我我没有满足 Iterator 特性。这是否可以通过安全防锈解决?
这是错误:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/iter_mut.rs:25:24
|
25 | self.obj.inner.get_mut(i)
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 22:5...
--> src/iter_mut.rs:22:5
|
22 | / fn next(&mut self) -> Option<Self::Item> {
23 | | let i = self.cursor;
24 | | self.cursor += 1;
25 | | self.obj.inner.get_mut(i)
26 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/iter_mut.rs:25:9
|
25 | self.obj.inner.get_mut(i)
| ^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 19:6...
--> src/iter_mut.rs:19:6
|
19 | impl<'a, T> Iterator for IterMut<'a, T> {
| ^^
note: ...so that the types are compatible
--> src/iter_mut.rs:22:46
|
22 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
23 | | let i = self.cursor;
24 | | self.cursor += 1;
25 | | self.obj.inner.get_mut(i)
26 | | }
| |_____^
= note: expected `std::iter::Iterator`
found `std::iter::Iterator`
Run Code Online (Sandbox Code Playgroud)
编辑:
next()以便迭代顺序是原始序列的排列。借用检查器无法证明后续调用next()不会访问相同的数据。之所以会出现这个问题,是因为借用的生命周期是迭代器的生命周期,所以不能证明不会同时对同一数据有两个可变引用。
如果没有不安全的代码或者改变你的数据结构,真的没有办法解决这个问题。你可以做slice::split_at_mut但是,考虑到你不能改变原始数据,你无论如何都必须在不安全的代码中实现它。不安全的实现可能如下所示:
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let i = self.cursor;
self.cursor += 1;
if i < self.obj.inner.len() {
let ptr = self.obj.inner.as_mut_ptr();
unsafe {
Some(&mut *ptr.add(i))
}
} else {
None
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2232 次 |
| 最近记录: |