I would like to define a struct that implements Iterator
such that the items yielded are references to one of the the struct's fields.
Lets say I have defined my struct like this:
struct InnerType;
struct MyStruct {
开发者_运维百科field: InnerType
}
The following does not work because the Associated Type Item
requires an explicit lifetime parameter:
impl Iterator for MyStruct {
type Item = &InnerType;
fn next(&mut self) -> Option<Self::Item> { Some(&self.field) }
}
Adding a lifetime parameter there doesn't work either because "the lifetime parameter 'a
is not constrained by the impl trait, self type, or predicates".
impl<'a> Iterator for MyStruct {
type Item = &'a InnerType;
fn next(&mut self) -> Option<Self::Item> { Some(&self.field) }
}
Not sure what I'm missing. What is going on here? Is there some reason(s) not to have an iterator which yields items borrowing from itself?
Is this really what you want? Or would you rather want it so that someone can request an iterator over MyStruct
, the way someone would call iter()
on a Vec
?
If that's the case, you're lucky. You just need a different struct actually implementing the Iterator
trait and that struct will contain a reference to field
.
struct InnerType;
struct MyStruct {
field: InnerType
}
struct MyIterator<'a> {
field: &'a InnerType
}
impl MyStruct {
fn iter<'a>(&'a self) -> MyIterator<'a> {
MyIterator{ field: &self.field }
}
}
impl<'a> Iterator for MyIterator<'a> {
type Item = &'a InnerType;
fn next(&mut self) -> Option<Self::Item> { Some(self.field) }
}
fn main() {
let foo: InnerType = InnerType{};
let my_struct = MyStruct{ field: foo };
let mut it = my_struct.iter();
let item = it.next();
assert!(item.is_some());
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=795bc0433a3a4e621486ecddf8f0a787
Otherwise, there's some discussions on here already about the issue with "streaming iterators", that is, iterators that return references to items in self.
See, for example, here: Iterator lifetime issue when returning references to inner collection
Now this mentions that Generic Associated Types would be required. And those have now made their way into stable Rust (1.65) but I'm not sure if that means that the standard Iterator
trait now supports that type of streaming iterator.
精彩评论