【问题标题】:How to resolve 'Vec<Peekable<dyn Iterator<Item = T>>> doesn't have a size known at compile-time'?如何解决 \'Vec<Peekable<dyn Iterator<Item = T>>> 在编译时没有已知大小\'?
【发布时间】:2022-09-23 11:10:06
【问题描述】:

我正在研究迭代器的笛卡尔幂实现。我遇到了一个障碍,我似乎无法存储我通过的迭代器的可窥视副本的向量。无论我如何使用框和指针,它都不起作用,因为Vec&lt;Peekable&lt;dyn Iterator&lt;Item = T&gt;&gt;&gt; 在编译时没有已知的大小。

关于如何在编译时知道这个大小的任何想法?我真的只需要存储一个指向向量的指针,对吗?没有理由不能在堆上创建它,是吗?

这是我到目前为止所拥有的(忽略 next() 实现,这只是为了测试我是否可以存储迭代器并正确使用它的下一个函数):

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

    标签: rust


    【解决方案1】:

    您不能直接存储Vec&lt;dyn Trait&gt;(或Vec&lt;Peekable&lt;dyn Trait&gt;&gt;),您必须使用间接寻址,因为每个元素可以有不同的大小:Vec&lt;Box&lt;Peekable&lt;dyn Iterator&lt;Item = T&gt;&gt;&gt;&gt;

    但是,由于您案例中的所有迭代器都是相同的,您可以使用泛型并避免Box 和动态调度的性能损失:

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

    【讨论】:

    • 避免拳击是要走的路。 FWIW,OP,这是拳击的样子:Playground
    猜你喜欢
    • 2020-06-13
    • 2022-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 2023-03-29
    • 2018-05-01
    • 2020-12-28
    相关资源
    最近更新 更多