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.
Iterator
doesn't allow the lifetime of itsItem
s 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.Vec
does nothing like what you're trying to do. Iterators should be separate from containers. – Spillway