如何移出Option的结构字段?

时间:2018-08-26 23:33:52

标签: rust copy borrow-checker

我想收集对结构的更改并立即应用所有更改。 基本轮廓如下:

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`

我找到了Get an enum field from a struct: cannot move out of borrowed content,并将#[derive(Clone, Copy)]添加到了枚举的定义中。

这可能有效,但是我对(隐式)使用复制感到不舒服,因为这通常也可能发生在较大的数据类型上。

实际所有者永远不会移出结构。

是否有另一种方法可以实现此目的,而又不会将Copy / Clone特征暴露给枚举的所有用户?

1 个答案:

答案 0 :(得分:9)

目前尚不清楚您对整个问题的处理程度,但是从本质上讲,如果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的内容所有权并设置{{ 1}}至OptionOption::take方法就是您想要的。

None