rust - 如何从引用结构的方法返回盒装闭包?

标签 rust closures lifetime

我有一个包含值的结构,我想获得一个对该值进行操作的函数:

struct Returner {
    val: i32,
}

impl<'a> Returner {
    fn get(&'a self) -> Box<Fn(i32) -> i32> {
        Box::new(|x| x + self.val)
    }
}

编译失败:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
 --> src/main.rs:7:18
  |
7 |         Box::new(|x| x + self.val)
  |                  ^^^^^^^^^^^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 5:1...
 --> src/main.rs:5:1
  |
5 | impl<'a> Returner {
  | ^^^^^^^^^^^^^^^^^
  = note: ...so that the types are compatible:
          expected &&Returner
             found &&'a Returner
  = note: but, the lifetime must be valid for the static lifetime...
  = note: ...so that the expression is assignable:
          expected std::boxed::Box<std::ops::Fn(i32) -> i32 + 'static>
             found std::boxed::Box<std::ops::Fn(i32) -> i32>

这是因为闭包借用了self,这对我来说没问题,因为我不打算在struct被销毁后使用获得的函数。根据我目前收集到的信息,有两种方法可以实现:

  1. 使用move 关键字。我不想使用它,因为它将获得该对象的所有权,并希望我在它返回此函数后使用它。

  2. 明确指定闭包的生命周期以告诉编译器它与调用它的结构体具有相同的生命周期。

我认为在我的情况下 2 是正确的方法,但我无法找到如何指定闭包的生命周期。有没有一种直接的方法可以做到这一点,或者我完全错了并且它与 Rust 生命周期逻辑相矛盾?

最佳答案

一般来说,你可以通过写Box<Trait + 'a>来指定一个装箱特征对象的生命周期。和其他类型指针后面的特征对象类似(如果省略它,它默认为 'static 至少在 Box 的情况下)。因此,在这种特定情况下,您需要返回类型 Box<(Fn(i32) -> i32) + 'a> .

但是,当您这样做时,您会看到另一个关于 self 的错误活得不够长。原因是(没有 move )闭包将捕获对局部变量 self 的引用。 。解决方案是使用 move .这不会移动 Returner对象,它移动 self这是对 Returner引用对象。

总结:

struct Returner {
    val: i32,
}

impl<'a> Returner {
    fn get(&'a self) -> Box<Fn(i32) -> i32 + 'a> {
        Box::new(move |x| x + self.val)
    }
}

关于rust - 如何从引用结构的方法返回盒装闭包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40544020/

相关文章:

rust - 为什么我在 where 子句中使用了泛型,但编译器仍然报告未使用?

generics - 处理 `Into` 泛型时的 Rust 生命周期问题

javascript - 如何在循环中创建闭包并将其存储在变量中供以后执行

rust - 向非引用类型添加生命周期约束

rust - Box<Any> 在 dylib 模块中向下转换返回 None

rust - 从 io::Result() 获取堆栈跟踪?

generics - 为什么我需要为不是结构成员的结构的通用参数提供生命周期?

rust - 为什么 Rust 中的通用生命周期参数可以专门用于一个对象的两个不相交的生命周期?

rust - 在闭包内使用 Vector,无需克隆

javascript - 谷歌 Dartlang 中关闭的奇怪行为