[solved] Is it possible to clone a boxed trait object?


#1

Suppose we have the following:

trait Foo { }
fn bar(baz: Box<Foo>) {
    let qux = baz.clone();
}

This will fail to compile with an error indicating that clone cannot be found for Box<Foo>.

Is there any way to require that implementers of Foo must also implement Clone such that all Box<Foo> can be cloned or something along those lines?


Reducing boilerplate in the "clone to Box" pattern
#2

Only if Foo is defined as Foo: Clone or the trait object is Box<Foo + Clone>, unless I’m forgetting something.


#3

You must have an implementation of Clone for Box<Foo>. Foo should not inherit Clone.


#4

I tried those two methods, here are the results:

trait Foo: Clone { }
fn bar(baz: Box<Foo>) {
    let qux = baz.clone();
}

This works in the test case provided above. Unfortunately, I am also doing:

impl<'a> PartialEq<Foo + 'a > for Foo + 'a {
    ...
}

When combined with the previous code I get an error indicating that Foo can no longer be made into an object.

With:

trait Foo { }
fn bar(baz: Box<Clone + Foo>) {
    let qux = baz.clone();
}

I receive an error because only builtin traits can be used as closure or object bounds.

I’m currently experimenting with workarounds such as changing the definition of Foo to:

trait Foo {
    fn box_clone(&self) -> Box<Foo>;
}

I feel that this solution isn’t very elegant though.


#5

Using box_clone() is the approach that works. Note that if you add that to the trait and use that to impl Clone for Box<Foo>, you can clone it as wanted.


#6

Thank you for your help bluss.

Here is the final code for others who may encounter this issue:

trait Foo {
    fn box_clone(&self) -> Box<Foo>;
}

impl Clone for Box<Foo>
{
    fn clone(&self) -> Box<Foo> {
        self.box_clone()
    }
}

#[derive(Clone)]
struct Bar;

impl Foo for Bar {
    fn box_clone(&self) -> Box<Foo> {
        Box::new((*self).clone())
    }
}

#[test]
fn it_works() {
    let baz = Box::new(Bar) as Box<Foo>;
    let qux = baz.clone();
}