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.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.