Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to resolve 'Vec<Peekable<dyn Iterator<Item = T>>> doesn't have a size known at compile-time'?

I’m working on a Cartesian power implementation for iterators. I’m running into a snag where I don’t seem able to store a vector of peekable copies of the iterator I’m passed. No matter how much I finagle with boxes and pointers, it doesn’t work due to Vec<Peekable<dyn Iterator<Item = T>>> not having a known size at compile time.

Any ideas for how to make this size be known at compile time? I really just need to be store a pointer to the vector, right? There’s no reason it can’t be created on the heap, is there?

Here’s what I have so far (ignore the next() implementation, that was just to test to see if I could store the iterator and correctly use it’s next function):

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

mod cartesian_power {
    use core::iter::Peekable;

    pub struct CartesianPower<T> {
        prototype: Box<dyn Iterator<Item = T>>,
        iters: Vec<Peekable<dyn Iterator<Item = T>>>,
    }

    impl<T> CartesianPower<T> {
        pub fn new<I>(vals: I, power: usize) -> CartesianPower<T>
        where
            I: IntoIterator<Item = T>,
            I: Clone,
            <I as IntoIterator>::IntoIter: 'static,
        {
            let iters = Vec::with_capacity(power);
            for _ in 0..power {
                iters.push(vals.clone().into_iter().peekable());
            }
            Self {
                prototype: Box::new(vals.into_iter()),
                iters: iters,
            }
        }

    }

    impl<T> Iterator for CartesianPower<T> {
        type Item = T;
        fn next(&mut self) -> Option<T> {
            self.prototype.next()
        }
    }
}

>Solution :

You cannot store a Vec<dyn Trait> (or Vec<Peekable<dyn Trait>>) directly, you have to use an indirection as each element can have a different size: Vec<Box<Peekable<dyn Iterator<Item = T>>>>.

However, since all iterators in your case are the same, you can use generics and avoid the performance hit of Box and dynamic dispatch:

pub struct CartesianPower<I: Iterator> {
    prototype: I,
    iters: Vec<Peekable<I>>,
}

impl<Iter: Iterator> CartesianPower<Iter> {
    pub fn new<I>(vals: I, power: usize) -> CartesianPower<Iter>
    where
        I: IntoIterator<IntoIter = Iter>,
        I: Clone,
        <I as IntoIterator>::IntoIter: 'static,
    {
        let mut iters = Vec::with_capacity(power);
        for _ in 0..power {
            iters.push(vals.clone().into_iter().peekable());
        }
        Self {
            prototype: vals.into_iter(),
            iters: iters,
        }
    }

}

impl<I: Iterator> Iterator for CartesianPower<I> {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> {
        self.prototype.next()
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading