Reputation: 5122
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":
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.
Upvotes: 6
Views: 629
Reputation: 10992
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.
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);
}
}
Upvotes: 3
Reputation: 88556
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. 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. In that case you can only solve your problem by restructuring your code, since Rust does not allow trait objects of multiple traits yet.
Upvotes: 2