如何为带盒装闭包的结构派生克隆?

How to derive Clone for structures with boxed closure?

我有以下结构:

struct MyStruct {
   foo: Box<dyn Fn(usize) -> usize>
}

我想为 MyStruct 导出 Clone。但是,编译器出现错误:

the trait bound `dyn std::ops::Fn(usize) -> usize: std::clone::Clone` is not satisfied

目前(rustc 1.46.0),dyn 不支持添加非自动特征,如 Box<dyn Fn(usize) -> usize + Clone>

来自rust-reference

A closure is Clone or Copy if it does not capture any values by unique immutable or mutable reference, and if all values it captures by copy or move are Clone or Copy, respectively.

所以我觉得这个推导在理论上是有道理的,但是我暂时不知道能不能做到。

我不介意为 MyStruct 手动实现 Clone,但我也不知道该怎么做。

我不想做类似

的事情
#[derive(Clone)]
struct MyStruct<F: Fn(usize) -> usize> {
    foo: F
}

因为这个结构被用作实现另一个特征结构的关联类型,而且那个结构和特征都没有泛型,我不想搞砸 PhantomData .

扩展上面的@mcarton 评论,但使用 dyn-clone 板条箱来克服 Clone 不是对象安全的问题,代码非常简单。

use dyn_clone::DynClone;

trait FnClone: DynClone {
    fn call(&self, x: usize) -> usize;
}

impl<F> FnClone for F
    where F: Fn(usize) -> usize + Clone
        
{
    fn call(&self, x: usize) -> usize {
        self(x)
    }
}

struct MyStruct {
   foo: Box<dyn FnClone>
}

impl Clone for MyStruct {
    fn clone(&self) -> MyStruct {
        MyStruct {
            foo: dyn_clone::clone_box(&*self.foo),
        }
    }

}

fn main() {
    let a = MyStruct{
        foo: Box::new(|x| x + 1)
    };
    let b = a.clone();
    println!("{} {}", a.foo.call(1), b.foo.call(2));
}

这个 crate 还提供了一个宏 clone_trait_object! 来使 Clone 可以派生为 Box<dyn FnClone>,但你似乎不希望这样。