我想克隆一个盒状特征的载体.

好吧,然后我试着用Clone作为超级trait ,但这只会导致标题中的错误.我找不到解决办法.

以下是最低限度的工作实现(或者不工作,因为我无法克隆)

#![allow(dead_code, unused_macros)]
use std::fmt::Debug;

trait MusicElement: Debug + Clone {
    fn duration(&self) -> f32;
}

#[derive(Debug, Clone)]
struct Note<'a> {
    name: &'a str,
    duration: f32,
}

impl<'a> MusicElement for Note<'a> {
    fn duration(&self) -> f32 {
        self.duration
    }
}

#[derive(Debug, Clone)]
struct Pause {
    duration: f32,
}

impl MusicElement for Pause {
    fn duration(&self) -> f32 {
        self.duration
    }
}

#[derive(Debug, Clone)]
struct Sequence {
    elements: Vec<Box<MusicElement>>,
}

impl MusicElement for Sequence {
    fn duration(&self) -> f32 {
        self.elements.iter().map(|e| e.duration()).sum()
    }
}

fn main() {
    let a4 = |dur| Box::new(Note { name: "a4", duration: dur });
    let seq = Sequence { elements: vec![a4(0.25), a4(0.25), a4(0.5)] };
    println!("{:?}", seq);
    let seq2 = seq.clone();
    println!("{:?}", seq2);
}

出现以下错误:

error[E0038]: the trait `MusicElement` cannot be made into an object
  --> src/main.rs:33:5
   |
33 |     elements: Vec<Box<MusicElement>>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MusicElement` cannot be made into an object
   |
   = note: the trait cannot require that `Self : Sized`

这里有一个link to the playground,便于代码运行.

我也试着把Sequence中的elements向量变成Vec<Box<MusicElement + Clone>>,但也没用.

我还没有在网上找到任何有用的解决方案,所以我的问题是:如何使代码可克隆?

推荐答案

解决方案在于结合到目前为止 comments 中的建议——@Lukas Kalbertodt's comment中的答案告诉您,必须为所有兼容('static + MusicElement + Clone)类型创建一个总括特征实现.实现所需的唯一后续步骤是将Note.name字段的类型从&'a str更改为Stringas metioned by @Boiethios:

#![allow(dead_code, unused_macros)]
use std::fmt::Debug;

trait MusicElement: MusicElementClone + Debug {
    fn duration(&self) -> f32;
}

trait MusicElementClone {
    fn clone_box(&self) -> Box<MusicElement>;
}

impl<T: 'static + MusicElement + Clone> MusicElementClone for T {
    fn clone_box(&self) -> Box<MusicElement> {
        Box::new(self.clone())
    }
}

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

#[derive(Debug, Clone)]
struct Note {
    name: String,
    duration: f32,
}

impl MusicElement for Note {
    fn duration(&self) -> f32 {
        self.duration
    }
}

#[derive(Debug, Clone)]
struct Pause {
    duration: f32,
}

impl MusicElement for Pause {
    fn duration(&self) -> f32 {
        self.duration
    }
}

#[derive(Debug, Clone)]
struct Sequence {
    elements: Vec<Box<MusicElement>>,
}

impl MusicElement for Sequence {
    fn duration(&self) -> f32 {
        self.elements.iter().map(|e| e.duration()).sum()
    }
}

fn main() {
    let a4 = |dur| Box::new(Note { name: String::from("a4"), duration: dur });
    let seq = Sequence { elements: vec![a4(0.25), a4(0.25), a4(0.5)] };
    println!("{:?}", seq);
    let seq2 = seq.clone();
    println!("{:?}", seq2);
}

这是编译的,所以它应该足够了!

Rust相关问答推荐

在HashMap中插入Vacant条目的可变借位问题

使用pyo3::Types::PyIterator的无限内存使用量

为什么这是&q;,而让&q;循环是无限循环?

类型批注需要静态生存期

在Rust 中移动原始指针的靶子安全吗

使用Rust WASM读取文件

如何实现Deref;多次;?

为什么RefCell没有与常规引用相同的作用域?

由于生存期原因,返回引用的闭包未编译

Rust 中多个 & 符号的内存表示

在发布中包含 Rust DLL

从嵌入式 Rust 中的某个时刻开始经过的时间

为什么我不能克隆可克隆构造函数的Vec?

判断对象是 PyDatetime 还是 Pydate 的实例?

如果我不想运行析构函数,如何移出具有析构函数的 struct ?

Cargo:如何将整个目录或文件包含在功能标志中?

你能用 Rust 和 winapi 制作 Windows 桌面应用程序吗?

如果返回类型是通用的,我可以返回 &str 输入的一部分吗?

如何在 Rust 中构建一个 str

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?