Rust坚持可克隆结构的泛型参数也必须实现Clone

n8ghc7c1  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(176)

Clone trait的文档说明了“如果所有字段都是Clone,这个trait可以与#[derive]一起使用。”我正在努力解决一个所有字段 * 都是 * Clone的情况,但是派生Clone不起作用。
请考虑以下简化示例(Playground link):

use std::fmt;
use std::rc::Rc;

trait Printer: Clone {
    fn print(&self) -> ();
}

# [derive(Clone)]

struct ClosurePrinter<T: fmt::Display> {
    get_value: Rc<dyn Fn() ->T>,
}

impl<T: fmt::Display> ClosurePrinter<T> {
    pub fn new(get_value: Rc<dyn Fn() -> T>) -> ClosurePrinter<T> {
        ClosurePrinter { get_value }
    }
}

impl<T: fmt::Display> Printer for ClosurePrinter<T> {
    fn print(&self) -> () {
        println!("{}", (self.get_value)())
    }
}

结构体ClosurePrinter有一个字段get_value: Rc<dyn Fn() -> T>Rc实现了Clone,所以我假设get_valueClone,但是编译器坚持T也必须是Clone

error[E0277]: the trait bound `T: Clone` is not satisfied
  --> src/lib.rs:19:23
   |
19 | impl<T: fmt::Display> Printer for ClosurePrinter<T> {
   |                       ^^^^^^^ the trait `Clone` is not implemented for `T`
   |
note: required because of the requirements on the impl of `Clone` for `ClosurePrinter<T>`
  --> src/lib.rs:8:10
   |
8  | #[derive(Clone)]
   |          ^^^^^
note: required by a bound in `Printer`
  --> src/lib.rs:4:16
   |
4  | trait Printer: Clone {
   |                ^^^^^ required by this bound in `Printer`
   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider further restricting this bound
   |
19 | impl<T: fmt::Display + std::clone::Clone> Printer for ClosurePrinter<T> {
   |                      +++++++++++++++++++

为什么编译器坚持T必须是Clone

mkshixfv

mkshixfv1#

文档中的第二句应该对此进行解释
对于泛型结构,#[derive]通过在泛型参数上添加绑定的Clone来有条件地实现Clone
这就是derive宏的工作方式。而且这也是它 * 能够 * 工作的唯一方式,因为过程宏的执行发生在编译器能够推理这些trait边界是否必要之前。幸运的是,你可以通过手动实现Clone trait来解决这个问题。

use std::fmt;
use std::rc::Rc;

struct ClosurePrinter<T: fmt::Display> {
    get_value: Rc<dyn Fn() ->T>,
}

impl<T: fmt::Display> Clone for ClosurePrinter<T> {
    fn clone(&self) -> Self {
         let get_value = Rc::clone(&self.get_value);
         Self { get_value }
    }
}

相关问题