I would like to return a reference to an owned object that is in a collection (viz., a Vec), but I cannot seem to get the lifetimes correct. Here is what I first tried:
struct StringHolder {
strings: Vec<String>,
i: usize,
}
impl Iterator for StringHolder {
type Item<'a> = &'a String;
fn next(&mut self) -> Option<Self::Item> {
if self.i >= self.strings.len() {
None
} else {
self.i += 1;
Some(&self.strings[self.i])
}
}
}
fn main() {
let sh = StringHolder { strings: vec![], i: 0 };
for string in sh {
println!("{}", string);
}
}
I get an error that generic associated types are unstable and lifetimes do not match type in trait. I tried a few other iterations, but nothing seemed to work.
I gather that this may not be possible based on some things I've read, but then I can't seem to figure out how Vec does it itself. For example, I can use the following to simply iterate over the underlying Vec and return a reference on each iteration:
struct StringHolder {
strings: Vec<String>,
}
impl<'a> IntoIterator for &'a StringHolder {
type Item = &'a String;
type IntoIter = ::std::slice::Iter<'a, String>;
fn into_iter(self) -> Self::IntoIter {
(&self.strings).into_iter()
}
}
fn main() {
let sh = StringHolder { strings: vec!["A".to_owned(), "B".to_owned()] };
for string in &sh {
println!("{}", string);
}
}
So that makes me think it is possible, I just haven't figured out lifetimes yet. Thanks for your help.
Iteratordoesn't allow the lifetime of itsItems to vary with the lifetime of theself, but in your case the items are stored in the iterator and share its lifetime, so that's just not going to work.Vecdoes nothing like what you're trying to do. Iterators should be separate from containers.