如何从Rust中具有生命周期参数的结构体上的方法向函数传递闭包?

wyyhbhjk  于 2023-06-30  发布在  其他
关注(0)|答案(1)|浏览(102)

我有一个带有生命周期参数'a'的struct Foo:

struct Foo<'a> {
  /* snip */
}

我想传递一个闭包(包含Foo的一些字段)给一个任意函数,例如:

impl Foo<'_> {

  // ...

  pub fn do_something(&mut self) {
    self.some_object.do_something(
      Box::new(
        |a_parameter| {
          self.some_other_object.do_something_else(a_parameter);
        }
      )
    );
  }

  // ...

}

do_something的定义如下:

fn do_something(f: Box<dyn Fn(T)>) { /* snip */ }

我得到的错误是

cast requires that `'1` must outlive `'static`

其中'1是在Foo本身上实现的函数中对self的可变引用的生存期。
我认为问题在于我需要指定闭包(在盒子内)的寿命与定义它的函数(即作用域)的寿命一样长。我只是不知道如何做到这一点,我尝试了许多事情,例如,添加一个生命周期参数做某事,但没有成功。
谢谢!

编辑

一个(非工作)示例:

struct Bar {
  num: i32,
} 
impl Bar {
  fn do_something(&self, f: Box<dyn Fn(i32)>) {
    f(self.num);
  }
}

struct Foo<'a> {
  bar: &'a Bar,
  other_num: i32,
}

impl Foo<'_> {

  fn do_something(&self) {
    self.bar.do_something(
      Box::new(|n| {
        println!("{}", n + self.other_num);
      })
    );
  }

}

fn main() {
 
  let bar = Bar { num: 123, };
  let foo = Foo { bar: &bar, other_num: 456, };

  foo.do_something();

}
pinkon5k

pinkon5k1#

因为你将闭包作为trait对象(Box<dyn Fn(i32)>),所以有一个隐式的+ 'static绑定(Box<dyn Fn(i32) + 'static>),这意味着闭包不允许借用任何数据。但是要传递的闭包借用了&self。可以通过使用显式的生存期使参数更通用:

impl Bar {
    fn do_something<'a>(&self, f: Box<dyn Fn(i32) + 'a>) {
    //             ^^^^                          ^^^^^^
    // `f` is now allowed to borrow data for any lifetime `'a`
        f(self.num);
    }
}

可以省略

impl Bar {
    fn do_something(&self, f: Box<dyn Fn(i32) + '_>) {
        f(self.num);
    }
}

这是一个非常简单的例子。在更复杂的代码中,生存期要求可能比这更严格。

相关问题