问题描述
我正在尝试为类型为Vec<Vec<(K, V)>>
迭代器代码:
pub struct IterMut<'a, K: 'a, V: 'a> {
iter: &'a mut Vec<Vec<(K, V)>>,
ix: usize,
inner_ix: usize,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
while self.iter.len() < self.ix {
while self.iter[self.ix].len() < self.inner_ix {
self.inner_ix += 1;
let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
return Some((&k, &mut v));
}
self.ix += 1;
}
return None;
}
}
我得到的错误是:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:16:42
|
16 | let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
| ^^^^^^^^^^^^^^^^^^
|
help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<(&'a K, &'a mut V)>
--> src/main.rs:11:5
|
11 | fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
| ^
显然我有终身问题,但是我不知道如何告诉编译器这应该工作.
Apparently I have lifetime problems, but I don't know how to tell the compiler that this should work.
这是应该如何实现可变迭代器,还是有更好的方法?
Is this how you should implement the mutable iterator or is there a better way?
推荐答案
在调试神秘的错误消息时,我发现更容易尝试并尽可能地隔离问题.
When debugging cryptic error messages, I've found it easier to try and isolate the issue as much as possible.
第一步是将表达式分解为其基本组成部分,让我们首先拆分索引步骤:
The first step is to break the expression into its essential constituents, let's start by splitting the indexing steps:
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
while self.iter.len() < self.ix {
while self.iter[self.ix].len() < self.inner_ix {
self.inner_ix += 1;
let outer: &'a mut Vec<_> = self.iter;
let inner: &'a mut Vec<_> = &mut outer[self.ix];
let (ref k, ref mut v) = inner[self.inner_ix];
return Some((&k, &mut v));
}
self.ix += 1;
}
return None;
}
Index
特征假定其输出的生存期与接收器的生存期相关,因此要获得'a
生存期,我们需要接收器具有&'a
生存期,并且它向上传播,从而导致上面的代码.
The Index
trait assumes that the lifetime of its output is linked to that of its receiver, so to get a 'a
lifetime we need the receiver to have a &'a
lifetime, and it propagates upward, leading to the above code.
但是这里有一个问题:let outer: &'a mut Vec<_> = self.iter;
不会编译,因为可变引用不是Copy
.
However there's an issue here: let outer: &'a mut Vec<_> = self.iter;
will not compile because mutable references are not Copy
.
那么,如何从可变引用中获取可变引用(由于IndexMut
获取了可变引用,这是必须的)?
So, how does one get a mutable reference from a mutable reference (which must be possible since IndexMut
gets a mutable reference)?
一个使用重新借入:let outer: &'a mut Vec<_> = &mut *self.iter;
.
还有,哦:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> <anon>:16:45
|
16 | let outer: &'a mut Vec<_> = &mut *self.iter;
| ^^^^^^^^^^^^^^^
|
重新借出的引用对'a
无效,仅对self
的(未命名)生命周期有效!
The reborrowed reference is not valid for 'a
, it's valid only for the (unnamed) lifetime of self
!
为什么要生锈?为什么?
否则将是不安全的.
&mut T
保证不会混叠,但是您的方法可以创建混叠引用(如果您忘记了推进索引的话):
&mut T
is guaranteed NOT to be aliasing, however your method could create aliasing references (if you forgot to advance the index):
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
return Some((&k, &mut v));
}
即使您不这样做,也无法保证您没有rewind
方法允许后退".
And even if you don't, there's not guarantee that you don't have a rewind
method that would allow "stepping back".
TL; DR:您将要踩到一枚地雷,而是被引导到Stack Overflow;)
好的,但是您如何实现迭代器!.
当然,使用迭代器.正如Shepmaster(简短地)回答的那样,标准库中已经有类似的内容,其名称为 FlatMap
.诀窍是使用现有的迭代器来获取详细信息!
Well, using iterators, of course. As Shepmaster (briefly) answers, there is the equivalent in the standard library already in the guise of FlatMap
. The trick is to use existing iterators for the nitty-gritty details!
类似的东西:
use std::slice::IterMut;
pub struct MyIterMut<'a, K: 'a, V: 'a> {
outer: IterMut<'a, Vec<(K, V)>>,
inner: IterMut<'a, (K, V)>,
}
然后,您只要从inner
中消费即可,只要它提供了物品,而当空时,您可以从outer
中重新填充.
Then you consume from inner
as long as it provides items, and when empty you refill it from outer
.
impl<'a, K, V> MyIterMut<'a, K, V> {
fn new(v: &'a mut Vec<Vec<(K, V)>>) -> MyIterMut<'a, K, V> {
let mut outer = v.iter_mut();
let inner = outer.next()
.map(|v| v.iter_mut())
.unwrap_or_else(|| (&mut []).iter_mut());
MyIterMut { outer: outer, inner: inner }
}
}
impl<'a, K, V> Iterator for MyIterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
loop {
match self.inner.next() {
Some(r) => return Some((&r.0, &mut r.1)),
None => (),
}
match self.outer.next() {
Some(v) => self.inner = v.iter_mut(),
None => return None,
}
}
}
}
一个快速的测试案例:
fn main() {
let mut v = vec![
vec![(1, "1"), (2, "2")],
vec![],
vec![(3, "3")]
];
let iter = MyIterMut::new(&mut v);
let c: Vec<_> = iter.collect();
println!("{:?}", c);
}
打印:
[(1, "1"), (2, "2"), (3, "3")]
正如预期的那样,所以它并没有完全损坏,但是我希望我不必依靠&[]
是'static
的把戏(即,std::slice::IterMut
实现了Default
).
as expected, so it's not completely broken, but I wish I did not have to rely on the &[]
is 'static
trick (ie, that std::slice::IterMut
implemented Default
).
这篇关于Vec的可变迭代器Vec(K,V)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!