如何从具有对struct引用的方法中返回盒装闭包? [英] How do I return a boxed closure from a method that has a reference to the struct?

查看:53
本文介绍了如何从具有对struct引用的方法中返回盒装闭包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a structure that contains a value and I want to obtain a function that operates on this value:

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,这对我来说很好,因为在结构销毁后我不打算使用获得的函数.到目前为止,有两种方法使之成为可能:

This is because the closure borrows self, which is fine by me, because I don't intend to use the obtained function after the struct is destroyed. From what I've gathered so far, there's two ways to make it possible:

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

  1. Use the move keyword. I don't want to use it because it will take ownership on the object, and want I to use it after it has returned this function.

明确指定闭包的生存期,以告知编译器其寿命与从其调用的结构相同.

Explicitly specify the lifetime of the closure to tell the compiler that it has the same lifetime as the struct it was called from.

在我的情况下,我认为2是正确的方法,但是我无法找出如何指定闭包的生存期.有直接的方法可以做到吗,还是我做错了所有事情,并且与Rust的生存期逻辑相矛盾?

I think that 2 is the correct way in my situation, but I've not been able to find out how to specify the closure's lifetime. Is there a direct way to do it or I've got it all wrong and it contradicts Rust lifetime logic?

推荐答案

通常,您可以通过编写Box<Trait + 'a>以及类似地为其他类型指针后面的特征对象指定盒装特征对象的生存期(如果省略,至少在Box的情况下默认为'static.因此,在这种特定情况下,您需要返回类型为Box<(Fn(i32) -> i32) + 'a>.

In general, you can specify the lifetime of a boxed trait object by writing Box<Trait + 'a> and analogously for trait objects behind other kinds of pointers (if it's omitted, it defaults to 'static at least in the case of Box). So in this specific case you want the return type Box<(Fn(i32) -> i32) + 'a>.

但是,当您这样做时,会看到另一个有关self寿命不足的错误.原因是(没有move)闭包将捕获对局部变量self 的引用.解决方法是使用move.这不会移动Returner对象,它会将作为引用self移到Returner对象.

However, when you do that you will see another error about self not living long enough. The reason is that (without move) the closure will capture a reference to the local variable self. The solution is to use move. This does not move the Returner object, it moves self which is a reference to the Returner object.

总结:

struct Returner {
    val: i32,
}

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

这篇关于如何从具有对struct引用的方法中返回盒装闭包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆