Different implementations of a trait on a struct

What is the best way to implement different implementations of a trait on the same struct? Let's I have a struct containing items and I want to have different ways to iterate through them.

struct Batch {
    items: Vec<u8>,
    pos: usize,
}

impl Iterator [?? for one] for Batch {
    fn next(&mut self) -> Option<u8> {
        self.pos += 1;
        Some(self.items[self.pos])
    }
}

impl Iterator [?? for two] for Batch {
    fn next(&mut self) -> Option<u8> {
        self.pos += 2;
        Some(self.items[self.pos])
    }
}

So far I've used separate structs containing the original struct and each struct has its impl for the trait.

struct BatchIterOne {
    batch: Batch
}
impl Iterator for BatchIterOne {...}

struct BatchIterTwo {
    batch: Batch
}
impl Iterator for BatchIterTwo {...}

it works but feels a bit clunky. Is there a better way?

Iterator structs are usually ancillary structs and not your primary data holding struct, since they have to hold their own "where am I in the iteration" state. For example, Vec uses

If don't want to do this, we're back to your original question

You can't do this directly -- you can only have one implementation per concrete type (aka coherence). Using wrapper structs like you have done is a viable workaround. Depending on your use case, you might want to wrap &mut Batch instead of Batch itself.

I imagine your examples were just for illustration, but when it comes to iterators, another possibility is to just use existing combinators like StepBy.

2 Likes

Thanks for the quick reply. Good to know the different approaches and limitation to the general problem. Yes, the example is for illustration only.