Как мне выйти из поля структуры, которое является опцией?
Я хочу собрать изменения в структуру и применить их все сразу. Основная схема выглядит следующим образом:
enum SomeEnum {
Foo,
Bar,
}
struct SomeStruct {
attrib: SomeEnum,
next_attrib: Option<SomeEnum>,
}
impl SomeStruct {
pub fn apply_changes(&mut self) {
if let Some(se) = self.next_attrib {
self.attrib = se;
}
self.next_attrib = None;
}
}
, что приводит к следующей ошибке компилятора:
error[E0507]: cannot move out of borrowed content --> src/lib.rs:13:27 | 13 | if let Some(se) = self.next_attrib { | -- ^^^^ cannot move out of borrowed content | | | hint: to prevent move, use `ref se` or `ref mut se`
Я нашел получить поле перечисления из структуры: не может выйти из заимствованного содержания и добавил #[derive(Clone, Copy)]
к определению моего перечисления.
Это может сработать, но мне неудобно (неявно) использовать копирование, поскольку это обычно может произойти и с большими типами данных.
В фактический владелец никогда не выходит из структуры.
Есть ли другой способ выполнить это, не подвергая опасности Copy
/Clone
черты для всех пользователей перечисления?
1 ответ:
Неясно, насколько хорошо вы следуете общей проблеме, но, по сути, вы не можете присвоить значение
Один из способов сделать это-вручную заменить значение. Например, вы могли бы использоватьself.attrib
, если оно все еще принадлежитself.next_atrrib
. Это означает, что вам нужно удалить значение изself.next_attrib
, а затем передать право собственностиself.attrib
.std::mem::replace
:impl SomeStruct { pub fn apply_changes(&mut self) { let next_attrib = std::mem::replace(&mut self.next_attrib, None); if let Some(se) = next_attrib { self.attrib = se; } } }
Заменить значение на
None
и принять во владение текущее значение какnext_attrib
. Тогда вы можете взять значение и, если оно равноSome(_)
, вы можете поместить его содержимое вself.attrib
.Поскольку это относительно распространенный шаблон, однако, есть функция полезности на
Option
для обработки ситуаций, когда вы хотели бы взять на себя ответственность за содержимоеOption
и установитьOption
вNone
. Тот самыйOption::take
метод - это то, что вам нужно.impl SomeStruct { pub fn apply_changes(&mut self) { if let Some(se) = self.next_attrib.take() { self.attrib = se; } } }