Общий указатель в массивах ржавчины - PullRequest
1 голос
/ 29 февраля 2020

У меня есть два массива:

struct Data {
    all_objects: Vec<Rc<dyn Drawable>>;
    selected_objects: Vec<Rc<dyn Drawable>>;
}

selected_objects гарантируется как подмножество all_objects. Я хочу иметь возможность каким-то образом иметь возможность добавлять или удалять изменяемые ссылки на выбранные объекты.

Я могу достаточно легко добавить объекты в selected_objects:

Rc::get_mut(selected_object).unwrap().select(true);
self.selected_objects.push(selected_object.clone());

Однако, если я позже попробую:

for obj in self.selected_objects.iter_mut() {
    Rc::get_mut(obj).unwrap().select(false);
}

Это выдаст ошибку времени выполнения, которая соответствует документации для get_mut: «В противном случае возвращает None, поскольку изменение общего значения небезопасно».

Однако я действительно хочу иметь возможность доступа и вызова произвольных методов для обоих массивов, поэтому Я могу эффективно выполнять операции с выделением, а также все еще выполнять операции для всех объектов.

Кажется, Rc не поддерживает это, кажется, RefMut отсутствует Clone(), что позволяет мне положить его в несколько массивов, а также на самом деле не поддерживает dyn типов. Box также отсутствует Clone(). Итак, мой вопрос, как вы храните записываемые указатели в нескольких массивах? Есть ли другой тип умного указателя для этой цели? Нужно ли их вкладывать? Есть ли какая-то другая структура данных, более подходящая? Есть ли способ отказаться от доступной для записи ссылки?

1 Ответ

1 голос
/ 01 марта 2020

Хорошо, мне потребовалось немного проб и ошибок, но у меня есть уродливое решение:

struct Data {
    all_objects: Vec<Rc<RefCell<dyn Drawable>>>;
    selected_objects: Vec<Rc<RefCell<dyn Drawable>>>;
}

Rc позволяет хранить несколько ссылок на объект. RefCell делает эти ссылки изменяемыми. Теперь единственное, что мне нужно сделать, это вызывать .borrow() каждый раз, когда я использую объект.

Хотя это, кажется, работает и достаточно разумно, я все еще открыт для более чистых решений.

...