简体   繁体   English

可克隆的迭代器特征对象

[英]Clonable iterator trait object

I'm trying to define a struct with a clonable iterator object.我正在尝试使用可克隆的迭代器对象定义一个结构。 So far, I've reached to:到目前为止,我已经达到:

pub struct UseClonableIterator2<'a,T:'a> {
    it: &'a (Iterator<Item=T> + Clone)
}

Which does not compile because Clone is not a "builtin trait":无法编译,因为Clone不是“内置特征”:

x.rs:2:33: 2:38 error: only the builtin traits can be used as closure or object bounds [E0225]
x.rs:2     it: &'a (Iterator<Item=T> + Clone)
                                       ^~~~~           
x.rs:2:33: 2:38 help: run `rustc --explain E0225` to see a detailed explanation

One option might be to add another type parameter for the Iterator, but this complicates definitions and I'd rather avoid it.一种选择可能是为迭代器添加另一个类型参数,但这会使定义复杂化,我宁愿避免它。

Do you need dynamic dispatch?你需要动态调度吗? If not, you should use generic parameters instead of trait objects -- it doesn't necessarily complicate the definition.如果没有,您应该使用泛型参数而不是特征对象——它不一定会使定义复杂化。 Try this for example:试试这个,例如:

pub struct UseClonableIterator<I: Iterator + Clone> {
    it: I
}

Here you save the object that implements Iterator and Clone within your type.在这里,您将在您的类型中保存实现IteratorClone的对象。 If you just want to have a reference to it, this is of course possible, too:如果你只是想参考它,这当然也是可能的:

pub struct UseClonableIterator2<'a, I: Iterator + Clone + 'a> {
    it: &'a I
}

Note that in both examples we use static dispatch and monomorphization.请注意,在两个示例中,我们都使用静态分派和单态化。 This usually results in better performance.这通常会带来更好的性能。

However, this is not always possible -- sometimes dynamic dispatch with trait objects (like you tried to implement it) is needed.然而,这并不总是可能的——有时需要使用 trait 对象(就像你试图实现它)的动态调度。 In that case you can only solve your problem by restructuring your code, since Rust does not allow trait objects of multiple traits yet.在这种情况下,您只能通过重构代码来解决您的问题,因为 Rust 还不允许具有多个 trait 的 trait 对象。

If you need the iterator to be dynamically dispatched, meaning the Iterator implementation type cannot be a type parameter of UseClonableIterator , then I would solve this as follows using my dyn-clone crate.如果您需要动态调度迭代器,这意味着Iterator实现类型不能是UseClonableIterator的类型参数,那么我将使用我的dyn-clone crate 如下解决这个问题。


use dyn_clone::{clone_trait_object, DynClone};

trait ClonableIterator: Iterator + DynClone {}

impl<I: Iterator + DynClone> ClonableIterator for I {}

clone_trait_object!(<T> ClonableIterator<Item = T>);

#[derive(Clone)]
struct UseClonableIterator<T> {
    it: Box<dyn ClonableIterator<Item = T>>,
}

fn main() {
    let thing1 = UseClonableIterator {
        it: Box::new(vec![1, 2, 3].into_iter()),
    };

    let thing2 = thing1.clone();

    // prints 1 2 3 from thing1's iterator
    for i in thing1.it {
        println!("{}", i);
    }

    // prints 1 2 3 from thing2's iterator
    for i in thing2.it {
        println!("{}", i);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM