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):
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()
}
}