Because Clone
isn't object-safe (it would return the actual type, not Box<dyn Clone>
), you need a workaround. You can almost use the method from this question, except because you don't own the Iterator
trait, you need to make a new trait. (playground)
trait ClonableIterator: Iterator {
fn clone_box(&self) -> Box<dyn ClonableIterator<Item = Self::Item>>;
}
impl<T, I> ClonableIterator for T
where
T: Iterator<Item = I> + Clone + 'static,
{
fn clone_box(&self) -> Box<dyn ClonableIterator<Item = I>> {
Box::new(self.clone())
}
}
Then you can store a trait object of this trait in your struct.
counter: Box<dyn ClonableIterator<Item = usize>>
And you can implement Clone
for your struct using clone_box
.
impl<F> Clone for EquationIterator<F> {
fn clone(&self) -> Self {
EquationIterator {
counter: self.counter.clone_box(),
formula: self.formula.clone(),
}
}
}
You can also do this for the Fn
trait, which I've upgraded to FnMut
since it is now owned exclusively.
trait ClonableFnMut<T, O>: FnMut(T) -> O {
fn clone_box(&self) -> Box<dyn ClonableFnMut<T, O>>;
}
impl<F, T, O> ClonableFnMut<T, O> for F
where
F: FnMut(T) -> O + Clone + 'static,
{
fn clone_box(&self) -> Box<dyn ClonableFnMut<T, O>> {
Box::new(self.clone())
}
}
And then you can add it to the struct.
formula: Box<dyn ClonableFnMut<usize, F>>
And change your Clone
implementation.
formula: self.formula.clone_box()
I couldn't quite get this to work with dyn-clone, but there might be a way.
Note that you would need to implement Clone
manually anyway because the derive would make it conditional on F
being Clone
, which isn't necessary.