我在使用下面的代码时遇到问题。不可变迭代器工作正常,但可变迭代器给了我以下错误:
<块引用>无法为生命周期参数推断合适的生命周期 由于需求冲突导致的函数调用。
是否有可能在不使用不安全的 Rust 和坚持迭代器特性的情况下以某种方式修复这个错误?
代码:
struct Collection<T, const S: usize> {
data: Vec<T>
}
struct CollectionIterator<'a, T, const S: usize> {
item_index: usize,
collection: &'a Collection<T, S>
}
struct CollectionIteratorMut<'a, T, const S: usize> {
item_index: usize,
collection: &'a mut Collection<T, S>
}
impl<T: Clone, const S: usize> Collection<T, S> {
fn new(num_items: usize, default_value: T) -> Collection<T, S> {
Collection {
data: vec![default_value; num_items * S]
}
}
fn iter(&self) -> CollectionIterator<T, S> {
CollectionIterator {
item_index: 0,
collection: self
}
}
fn iter_mut(&mut self) -> CollectionIterator<T, S> {
CollectionIterator {
item_index: 0,
collection: self
}
}
}
impl<'a, T, const S: usize> Iterator for CollectionIterator<'a, T, S> {
type Item = &'a [T];
fn next(&mut self) -> Option<Self::Item> {
if self.item_index < self.collection.data.len() {
self.item_index += S;
Some(&self.collection.data[self.item_index - S .. self.item_index])
} else {
None
}
}
}
impl<'a, T, const S: usize> Iterator for CollectionIteratorMut<'a, T, S> {
type Item = &'a mut [T];
fn next(&mut self) -> Option<Self::Item> {
if self.item_index < self.collection.data.len() {
self.item_index += S;
Some(&mut self.collection.data[self.item_index - S .. self.item_index])
} else {
None
}
}
}
fn main() {
let mut c: Collection<f64, 3> = Collection::new(5, 0.0);
for x in c.iter_mut() {
x[0] = 100.0;
}
for x in c.iter() {
println!("{} {} {}", x[0], x[1], x[2]);
}
}
错误:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:52:23
|
52 | Some(&mut self.collection.data[self.item_index - S .. self.item_index])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 49:13...
--> src/main.rs:49:13
|
49 | fn next(&mut self) -> Option<Self::Item> {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:52:23
|
52 | Some(&mut self.collection.data[self.item_index - S .. self.item_index])
| ^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 47:6...
--> src/main.rs:47:6
|
47 | impl<'a, T, const S: usize> Iterator for CollectionIteratorMut<'a, T, S> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:49:46
|
49 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
50 | | if self.item_index < self.collection.data.len() {
51 | | self.item_index += S;
52 | | Some(&mut self.collection.data[self.item_index - S .. self.item_index])
... |
55 | | }
56 | | }
| |_____^
= note: expected `Iterator`
found `Iterator`
答案 0 :(得分:0)
fn next(&mut self) -> Option<Self::Item> {
if self.item_index < self.collection.data.len() {
self.item_index += S;
Some(&mut self.collection.data[self.item_index - S .. self.item_index])
} else {
None
}
}
您编写的代码将生成一系列对 self.collection
不同部分的可变引用。但是编译器(借用检查器)不会对索引算法进行任何分析来确定它们实际上是不重叠的。因此,此代码被拒绝。一般来说,如果没有不安全的代码,就无法编写向集合中生成可变引用的迭代器,因为借用检查器理解的唯一一种非重叠引用是不同的结构/元组字段。
但是,您不需要编写不安全的代码来解决这个特定问题,因为 std::slice::ChunksMut
返回的迭代器 <[T]>::chunks_mut
已经包含您需要的实现。非可变 chunks()
也可以替换您的其他迭代器实现。
impl<T: Clone, const S: usize> Collection<T, S> {
fn new(num_items: usize, default_value: T) -> Collection<T, S> {
Collection {
data: vec![default_value; num_items * S]
}
}
fn iter(&self) -> impl Iterator<Item = &[T]> + '_ {
self.data.chunks(S)
}
fn iter_mut(&mut self) -> impl Iterator<Item = &mut [T]> + '_ {
self.data.chunks_mut(S)
}
}