Sassa NF
Sassa NF

Reputation: 5406

How to hold a Peekable of any iterator in a struct?

I have a struct:

struct Quads<'a> {
    mx: &'a Vec<Vec<u32>>,
    xs: &'a mut Peekable<Range<i32>>,
    ys: &'a mut Peekable<Range<i32>>,
    dx: i32,
    dy: i32,
}

I wanted the type of xs to be Peekable<dyn Iterator<Item = i32>>, as that would be a natural thing to want in other languages. Is such an idea expressible in Rust?

That is, "a Peekable of some Iterator of i32", not a Peekable of a specific Iterator.

Upvotes: 1

Views: 896

Answers (1)

kmdreko
kmdreko

Reputation: 60052

The problem with Peekable<dyn Iterator<Item = i32>> is that dyn Trait represents a type dynamically (obviously) which means that it is a dynamically sized type. Those cannot be expressed directly as a struct field (except through obscure means).

So @edwardw's comment is the way to go. Putting the iterator in a Box ensures the field has a fixed size but the iterator itself can be whatever size it wants. Box also naturally implements Iterator if the contents implement Iterator. Here's the changes (also following your lead in your other Q&A that they should be stored directly and not as &mut references):

struct Quads<'a> {
    mx: &'a Vec<Vec<u32>>,
    xs: Peekable<Box<dyn Iterator<Item = i32>>>,
    ys: Peekable<Box<dyn Iterator<Item = i32>>>,
    dx: i32,
    dy: i32,
}

Which you can then create via Box::new(0..dx) as Box<dyn Iterator<Item = i32>> (playground).

If the expected concrete type is Range<i32> then this probably isn't a problem, but if you did want to store more exotic iterators that require lifetimes, then you may need to add a + 'a constraint as shown in this answer: How can I make Box<dyn Iterator> peekable and avoid lifetime errors?

Upvotes: 1

Related Questions