の面白い点by_ref()は、それ自体への変更可能な参照を返すことです。
pub trait IteratorExt: Iterator + Sized {
fn by_ref(&mut self) -> &mut Self { self }
}
これは、Iterator型へのミュータブル ポインターIteratorに対してトレイトが実装されているため機能します。頭いい!
impl<'a, I> Iterator for &'a mut I where I: Iterator, I: ?Sized { ... }
標準関数は、自動的に に解決されるtake_whiletrait を使用するため機能します。Iterator&mut Peekable<T>
しかしPeekable、特性ではなく構造体であるため、コードは機能しません。そのためCautiousTakeWhileable、型を指定する必要があり、その所有権を取得しようとしていますが、変更可能なポインターがあるため、できません。
Peekable<T>解決策、 butは使用しないでください&mut Peekable<T>。ライフタイムも指定する必要があります。
impl <'a, T: Iterator, P> Iterator for CautiousTakeWhile<&'a mut Peekable<T>, P>
where P: FnMut(&T::Item) -> bool {
//...
}
impl <'a, T: Iterator> CautiousTakeWhileable for &'a mut Peekable<T> {
fn cautious_take_while<P>(self, f: P) -> CautiousTakeWhile<&'a mut Peekable<T>, P>
where P: FnMut(&T::Item) -> bool {
CautiousTakeWhile{inner: self, condition: f,}
}
}
このソリューションの奇妙な副作用は、変更可能な参照を使用するため、所有権を盗まないby_refため、現在は必要ないということです。cautious_take_while()またはのいずれかを取ることができ、デフォルトで最初のものになるためby_ref()、呼び出しが必要です。呼び出しにより、2 番目のものに解決されます。take_while()Peekable<T>&mut Peekable<T>by_ref()
そして、ようやく理解できたので、 の定義を変更struct CautiousTakeWhileして、構造体自体にピーク可能なビットを含めることをお勧めします。難点は、私が正しければ、寿命を手動で指定する必要があることです。何かのようなもの:
struct CautiousTakeWhile<'a, T: Iterator + 'a, P>
where T::Item : 'a {
inner: &'a mut Peekable<T>,
condition: P,
}
trait CautiousTakeWhileable<'a, T>: Iterator {
fn cautious_take_while<P>(self, P) -> CautiousTakeWhile<'a, T, P> where
P: FnMut(&Self::Item) -> bool;
}
残りは多かれ少なかれ簡単です。