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

3

如何正确地从表达式返回一个装箱的可克隆迭代器?例如:

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个回答

2

Iterator是一个特质(trait),因此Box<Iterator>是一个特质对象(trait object)。

Clone不能被转换为一个特质对象,因为它需要了解Self,所以我们按照如何克隆存储特质对象的结构体?中的说明进行操作:

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

另请参见:


请问你能解释一下这里的 static 生命周期是什么意思吗?如果我把它移除掉,就会出现 T may not live long enough 的错误。我无法理解在什么情况下,如果编译器忽略了这个错误,代码会崩溃。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接