Не могу клонировать Vecпотому что черта не может быть превращена в объект - PullRequest
0 голосов
/ 25 апреля 2018

Я пытаюсь клонировать вектор в штучной упаковке. Естественно, просто получить Clone на всех структурах, которые реализуют мою черту, недостаточно, потому что компилятор не знает во время компиляции, что все структуры, реализующие черту, имеют Clone.

Хорошо, тогда я попытался использовать Clone в качестве супертрейта, но это привело к ошибке в названии. Я в недоумении для решений.

Вот минимальная рабочая реализация (или не работает, так как я не могу клонировать)

#![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`

А вот ссылка на игровую площадку для удобства выполнения кода.

Я также пытался сделать вектор elements в Sequence a Vec<Box<MusicElement + Clone>>, но это тоже не сработало.

Мне не удалось найти каких-либо полезных решений в Интернете, поэтому вот мой вопрос: как сделать код клонируемым?

Ответы [ 2 ]

0 голосов
/ 10 июня 2018

Мой objekt ящик обеспечивает многоразовую реализацию ответа Джонни .С его помощью вы можете заставить свой оригинальный код работать с минимальным количеством изменений.


До:

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

После:

#[macro_use]
extern crate objekt;

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

clone_trait_object!(MusicElement);

// Everything else as you wrote it.
0 голосов
/ 25 апреля 2018

Решение состоит в том, чтобы объединить предложения в комментариях - ответ в @ комментарии Лукаса Калбертодта говорит вам, что вы должны создать реализацию общей черты для всех совместимых ('static + MusicElement + Clone) типов.Единственный последующий шаг, необходимый для вашей реализации, - это изменение типа поля Note.name с &'a str на String, , как указано @ 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);
}

.должно хватить!

...