の面白い点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_while
trait を使用するため機能します。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;
}
残りは多かれ少なかれ簡単です。