2

我有以下代码片段,它实现了某种发射器结构:

type Callback<'a> = Option<&'a mut dyn FnMut()>;

struct Emitter<'a> {
  cb: Callback<'a>
}

impl<'a> Emitter<'a> {

  fn emit(&mut self) {
    if self.cb.is_some() {
      let f = self.cb.unwrap();
      f()
    }
  }
}

fn main() {

  let mut cb = || println!("test");

  let mut e = Emitter { 
    cb : Some(&mut cb)
  };
  
  e.emit();
}

emit() 函数尝试运行保存的回调 clojure。但是我无法理解如何运行回调,因为代码会产生以下错误:

  --> src/main.rs:11:15
   |
11 |       let f = self.cb.unwrap();
   |               ^^^^^^^
   |               |
   |               move occurs because `self.cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait
   |               help: consider borrowing the `Option`'s content: `self.cb.as_ref()`

感谢一些帮助:)

这是关于 replit 的片段:https ://replit.com/@lutzer/RustEmitterTest

4

1 回答 1

3

这里发生的事情是你的线路

let f = self.cb.unwrap();

想要将闭包移出Option枚举。此操作使用枚举,这对于属于结构的事物是不允许的。

这是一个更简单的示例来说明我的意思:

fn main() {
  let an_option = Some(String::from("Woot!");
  let the_value = an_option.unwrap();
  println!("The value is {}", the_value);

  println!("The option is {:?}", an_option); // error here! Can't use an_option any more!!!

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4a4a3660b68ebada99113db5165b6e76

So if you take ownership of something stored inside the Some part of an Option, via unwrap, then the whole Option gets moved out. You can see that in the signature of unwrap:

pub const fn unwrap(self) -> T

Note how it says self, and not &self or &mut self. That means, after calling unwrap, that the enum gets consumed and cannot be used any more, unless the value inside the Some part can simply be copied (If you replace the String in my example with, say, an integer, it will compile without issue).

The comment by Omer Erden then explains a way around that: Ask the Option to give you a mutable reference instead via as_mut.

Or skip all that directly and use the map method of option, which you can use to do something if the option is Some and just not do anything if it's None.

于 2021-08-27T02:42:10.733 回答