Reputation: 2390
I have a Vec<Point>
with a simple struct Point {x: f32, y: f32, z: f32}
. My vector represents hundreds of thousands of lines in 3D (it could be a Vec<Vec<Point>>
in fact), so I keep track of the start/end of all lines.
pub struct Streamlines {
lengths: Vec<usize>,
offsets: Vec<usize>, // cumulative sum of lengths
data: Vec<Point>,
}
I want to create a non-consuming iterator for it, usable like:
for streamline in &streamlines {
for point in &streamline {
println!("{} {} {}", point.x, point.y, point.z);
}
println!("")
}
I found How to implement Iterator and IntoIterator for a simple struct? and started copyi-err, adapting :)
impl IntoIterator for Streamlines {
type Item = &[Point];
type IntoIter = StreamlinesIterator;
fn into_iter(self) -> Self::IntoIter {
StreamlinesIterator {
streamlines: self,
it_idx: 0
}
}
}
struct StreamlinesIterator {
streamlines: &Streamlines,
it_idx: usize
}
impl Iterator for StreamlinesIterator {
type Item = &[Point];
fn next(&mut self) -> Option<&[Point]> {
if self.it_idx < self.streamlines.lengths.len() {
let start = self.streamlines.offsets[self.it_idx];
self.it_idx += 1;
let end = self.streamlines.offsets[self.it_idx];
Some(self.streamlines.data[start..end])
}
else {
None
}
}
}
I used slices because I only want to return parts of the vector, then I added lifetimes because it's required, but now I have this error cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
In fact, I don't actually know what I'm doing with the damn <'a>
.
Upvotes: 2
Views: 496
Reputation: 431599
cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
That's because you aren't correctly implementing Iterator
and have something like this:
impl<'a> Iterator for StreamlinesIterator<'a> {
type Item = &'a [Point];
fn next(&mut self) -> Option<&[Point]> { /* ... */ }
// ...
}
Due to lifetime inference, this is equivalent to:
impl<'a> Iterator for StreamlinesIterator<'a> {
type Item = &'a [Point];
fn next<'b>(&'b mut self) -> Option<&'b [Point]> { /* ... */ }
// ...
}
This is attempting to return a reference that lives as long as the iterator, which you cannot do.
If you correctly implement Iterator
, it works:
impl<'a> Iterator for StreamlinesIterator<'a> {
type Item = &'a [Point];
fn next(&mut self) -> Option<&'a [Point]> { /* ... */ }
// Even better:
fn next(&mut self) -> Option<Self::Item> { /* ... */ }
// ...
}
I don't actually know what I'm doing with the damn
<'a>
.
You should go back and re-read The Rust Programming Language, second edition. When you have specific questions, Stack Overflow, IRC, the User's Forum will all be waiting.
Upvotes: 7