Как мне выйти из поля структуры, которое является опцией? - PullRequest
0 голосов
/ 27 августа 2018

Я хочу собрать изменения в структуре и применить их все сразу.Основная схема выглядит следующим образом:

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)] к определению моего enum.

Это может сработать, но я чувствую себя неловко из-за (неявного) использования копирования, так как это обычно может происходить и с более крупными типами данных.

Фактический владелец никогда не перемещается из структуры.

Есть ли другой способ сделать это, не раскрывая черты Copy / Clone всем пользователям перечисления?

1 Ответ

0 голосов
/ 27 августа 2018

Неясно, насколько хорошо вы следите за общей проблемой, но, по сути, вы не можете присвоить значение 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;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...