Dynami c рассылка по обобщенной c структуре без дополнительной черты - PullRequest
0 голосов
/ 12 апреля 2020

Учитывая следующую настройку:

trait MyTrait {}

struct TraitContainer<T: MyTrait> {
  inner: T
}

Я хочу создать Vec<TraitContainer<_>>, где каждый контейнер может иметь свою реализацию свойств. Наивным способом было бы удалить универсальный параметр c и заменить его на Vec<TraitContainer<Box<dyn MyTrait>>>. Но я чувствую, что мне не нужно. Я хочу сделать что-то вроде Vec<Box<dyn TraitContainer<MyTrait>>>, и это кажется , как будто это возможно, но я действительно не знаю, как заставить это работать.

Полная настройка игровой площадки


Чтобы поместить мою идею в другой контекст: если у меня есть Vec<Box<dyn MyTrait>>, каждый раз, когда я хочу получить доступ к объекту, он будет выполнять динамическую c диспетчеризацию, чтобы найти правильную реализацию черты характера. Но если я знаю, что все предметы моего Ve c будут иметь одинаковый тип (я просто не знаю точного, только что они реализуют какую-то черту), я должен быть в состоянии сделать Box<dyn Vec<MyTrait>>. Таким образом, у меня все еще есть динамическая отправка c, но я перешел на самый внешний уровень вложенности.

1 Ответ

0 голосов
/ 15 апреля 2020

Оказывается, это довольно просто: TraitContainer должен быть помечен как размер:

trait MyTrait {}

struct Foo;

impl MyTrait for Foo {}

struct TraitContainer<T: MyTrait + ?Sized>(T); // <--- "+ ?Sized"

impl MyTrait for Box<dyn MyTrait> {
}

fn main() {
    let works: TraitContainer<Foo> = TraitContainer(Foo);
    let still_works: TraitContainer<Box<dyn MyTrait>> = TraitContainer(Box::new(Foo));
    let yay: Box<TraitContainer<dyn MyTrait>> = Box::new(TraitContainer(Foo));
}

Предостережение заключается в том, что это не работает с другим примером, потому что Vec<T> требует T: Sized. Так что Box<Vec<dyn MyTrait>> не скомпилируется.

...