如何在Rust中返回一个盒装的可克隆迭代器?

时间:2018-04-01 04:12:21

标签: iterator rust

从表达式返回盒装克隆迭代器的正确方法是什么?例如:

fn example() -> Box<Iterator<Item = String> + Clone> {
    unimplemented!()
}

这给我一个错误,只能以这种方式指定自动特征:

error[E0225]: only auto traits can be used as additional traits in a trait object
 --> src/main.rs:1:47
  |
1 | fn example() -> Box<Iterator<Item = String> + Clone> {
  |                                               ^^^^^ non-auto additional trait

这是我的真实代码:

let my_iterator = {
    if a {
        Box::new(/* ... */) as Box<Iterator<Item = String> + Clone>
    } else {
        Box::new(/* ... */) as Box<Iterator<Item = String> + Clone>
    }
};
let pb = ProgressBar::new(my_iterator.clone().count() as u64);

如果考虑其他建议:两个分支代表一个从文件加载的路径,另一个路径用于自动生成,如果不需要,我宁愿不将内容保存在内存中。

1 个答案:

答案 0 :(得分:2)

Iterator trait ,因此Box<Iterator>特质对象

Clone无法成为特质对象,因为它需要了解Self,因此我们按照How to clone a struct storing a boxed trait object?中的说明操作:

trait CloneIterator: Iterator {
    fn clone_box(&self) -> Box<CloneIterator<Item = Self::Item>>;
}

impl<T> CloneIterator for T
where
    T: 'static + Iterator + Clone,
{
    fn clone_box(&self) -> Box<CloneIterator<Item = Self::Item>> {
        Box::new(self.clone())
    }
}

fn example(switch: bool) -> Box<CloneIterator<Item = String>> {
    let i = vec!["a".into(), "b".into()].into_iter();
    if switch {
        Box::new(i)
    } else {
        Box::new(i.take(1))
    }
}

fn main() {
    let i = example(true);
    let i2 = i.clone_box();

    let j = example(false);
    let j2 = j.clone_box();
}

另见: