首页 > 解决方案 > 如何使用消耗此成员本身的此成员方法替换结构的成员?

问题描述

我有一个枚举,它可能包含一个向量。我为枚举实现了一个方法,它可以生成一个新的枚举,它在以前的枚举中重用相同的向量(我不想复制向量)。生成新的枚举后,我将不再使用以前的枚举,所以我实现了这个方法fn (self),它将获得枚举的所有权。

然后我把enum放到一个结构体中,我想用我刚刚实现的enum的方法来替换结构体中的enum。但我得到了这个错误:

error[E0507]: cannot move out of borrowed content
  --> src/lib.rs:22:18
   |
22 |         self.0 = self.0.get_a_new_foo();
   |                  ^^^^^^ cannot move out of borrowed content

有什么办法可以修复我的代码吗?

enum Foo {
    A,
    B(Vec<u32>),
}

impl Foo {
    fn get_a_new_foo(self) -> Foo {
        match self {
            Foo::A => Foo::B(vec![]),
            Foo::B(mut v) => {
                let len = v.len() as u32;
                v.push(len - 1);
                Foo::B(v)
            }
        }
    }
}

struct Bar(Foo);
impl Bar {
    fn replace_foo(&mut self) -> () {
        self.0 = self.0.get_a_new_foo();
    }
}

标签: rustlifetimeownership

解决方案


您可以使用take_mut箱优雅地做到这一点:

struct Bar(Foo);
impl Bar {
    fn replace_foo(&mut self) -> () {
        take_mut::take(&mut self.0, |foo| foo.get_a_new_foo());
    }
}

或者,无需其他依赖项,您可以这样做:

struct Bar(Foo);
impl Bar {
    fn replace_foo(&mut self) -> () {
        let mut tmp = Foo::A;
        std::mem::swap(&mut tmp, &mut self.0);
        tmp = tmp.get_a_new_foo();
        std::mem::swap(&mut tmp, &mut self.0);
    }
}

但它只有在你可以廉价地构建一些“占位符”变体时才有效Foo,就像Foo::A在这种情况下一样。


推荐阅读