わかりにくいエラーメッセージをデバッグする際には、問題をできるだけ簡単に解決してください。
最初のステップは、その本質的な構成要素への発現を破るのは、インデックス手順を分割することによって開始させることです。
Index
形質は、その出力の寿命はその受信機のそれにリンクされていることを前提としてい
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;
}
、したがって'a
の生涯を得るためには、受信者は&'a
の生涯を持つ必要があり、それは上方に伝播して上記のコードにつながります。
ただし、ここに問題があります:let outer: &'a mut Vec<_> = self.iter;
は、可変参照がCopy
ではないため、コンパイルできません。
可変参照からどのように可変参照を取得するのですか(IndexMut
は可変参照を取得するので可能でしょう)。
1つは再借用を使用します: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;
| ^^^^^^^^^^^^^^^
|
reborrowed参照が'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
です。
TL; DR:あなたは、あなたの代わりにスタックオーバーフローに向かって操縦された地雷を踏むことを約あった。)あなたはイテレータを実装するのですか
よしのが、!。
もちろん、イテレータを使用します。 Shepmaster(簡潔に)が答えると、すでに標準ライブラリに相当するものがFlatMap
と見なされます。このトリックは、既存のイテレーターを使って細かいディテールを作成することです!以下のような
何か:あなたはouter
からそれを補充する際に空
use std::slice::IterMut;
pub struct MyIterMut<'a, K: 'a, V: 'a> {
outer: IterMut<'a, Vec<(K, V)>>,
inner: IterMut<'a, (K, V)>,
}
は、次に、あなたがいる限り、それはアイテムを提供してinner
から消費、および。
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
)。
うわー!ありがとう!これは本当に素晴らしい答えです!私は実際にカスタムハッシュマップに取り組んでいます。 –
'unwrap_or_else(...)'は 'outer'が空の場合に使用されますか? –
@JesperAxelsson:そうです。しかし、私は、空のスライスへの変更可能な参照が ''静的な存続期間を持つことができるというトリックを使用して、安全でないコードを使用しないようにそのビットを更新しました。 @MatthieuMはこのことについて知らなかった。 :) –