我正在尝试为类型为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)> {
| ^
显然我有生命问题,但我不知道如何告诉编译器这应该有用。
这是你应该如何实现可变迭代器还是有更好的方法?
答案 0 :(得分:6)
在调试神秘的错误消息时,我发现尝试尽可能地解决问题更容易。
第一步是将表达式分解为其基本组成部分,让我们从分割索引步骤开始:
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
生命周期,并且它向上传播,导致上面的代码。
但是这里存在一个问题:let outer: &'a mut Vec<_> = self.iter;
将无法编译,因为可变引用不是Copy
。
那么,如何从可变引用中获取可变引用(由于IndexMut
获得可变引用,这必须是可能的?)
一个人使用重新借用: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
的(未命名)生命周期有效!
为什么生锈?为什么?
因为否则会不安全。
&mut T
保证不会出现别名,但是您的方法可能会创建别名引用(如果您忘记推进索引):
#[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
方法允许&#34;踩到&#34;。
TL; DR:您即将踩到地雷,而是转向Stack Overflow;)
好的,但如何实现迭代器!。
当然,使用迭代器。正如Shepmaster(简要地)回答的那样,标准库中的等价物已经以FlatMap
为幌子。诀窍是使用现有的迭代器来获取细节!
类似的东西:
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
重新填充。
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
已实施{ {1}})。
答案 1 :(得分:3)
您没有提供重新实施标准Iterator::flat_map
的理由,所以我只是使用它而另一个map
来消除您不需要的可变性:
fn main() {
let mut a: Vec<Vec<(u8, u8)>> = Default::default();
let c = a.iter_mut()
.flat_map(|x| x.iter_mut())
.map(|&mut (ref a, ref mut b)| (a, b))
.count();
println!("{}", c);
}
完成后,您可以return the iterator in one of the many ways。
#[derive(Debug, Default)]
struct Thing<K, V>(Vec<Vec<(K, V)>>);
impl<K, V> Thing<K, V> {
fn iter_mut<'a>(&'a mut self) -> Box<Iterator<Item = (&'a K, &'a mut V)> + 'a> {
Box::new(self.0
.iter_mut()
.flat_map(|x| x.iter_mut())
.map(|&mut (ref a, ref mut b)| (a, b)))
}
}
fn main() {
let mut a = Thing::<u8, u8>::default();
let c = a.iter_mut().count();
println!("{}", c);
}