存储捕获返回值的闭包时存在冲突的生命周期要求

Conflicting lifetime requirements when storing closure capturing returned value

编辑:

我正在尝试在函数内创建一个闭包向量,向该向量添加一个标准闭包,然后 return 从该函数创建向量。我收到有关生命周期冲突的错误消息。

代码可以执行 here.

fn vec_with_closure<'a, T>(f: Box<FnMut(T) + 'a>) -> Vec<Box<FnMut(T) + 'a>>
{
    let mut v = Vec::<Box<FnMut(T)>>::new();
    v.push(Box::new(|&mut: t: T| {
        f(t);
    }));
    v
}

fn main() {
    let v = vec_with_closure(Box::new(|t: usize| {
        println!("{}", t);
    }));
    for c in v.iter_mut() {
        c(10);
    }
}

编辑 2:

使用 Rc<RefCell<...>>move ||Fn() 特性而不是 Shepmaster 建议的 FnMut()m,帮助我生成了上述的工作版本代码。 Rust 围栏版本 here.

以下是我对问题的理解,略有简化:

fn filter<F>(&mut self, f: F) -> Keeper
    where F: Fn() -> bool + 'static //'
{
    let mut k = Keeper::new();
    self.subscribe(|| {
        if f() { k.publish() }
    });
    k
}

在这个方法中,f是一个传值过来的值,也就是说filter拥有它。然后,我们创建另一个闭包来捕获 f by-reference。然后我们试图将该闭包保存在某个地方,因此闭包中的所有引用都需要超过我们结构的生命周期(为了方便我选择 'static)。

然而,f 只存活到方法结束,因此它肯定不会存活足够长的时间。我们需要让闭包拥有 f。如果我们可以使用 move 关键字,那将是理想的,但这会导致闭包也移入 k,因此我们无法从函数中 return 它。

试图解决导致此版本的问题:

fn filter<F>(&mut self, f: F) -> Keeper
    where F: Fn() -> bool + 'static //'
{
    let mut k = Keeper::new();
    let k2 = &mut k;
    self.subscribe(move || {
        if f() { k2.publish() }
    });
    k
}

其中有一条有用的错误信息:

error: `k` does not live long enough
let k2 = &mut k;
              ^
note: reference must be valid for the static lifetime...
...but borrowed value is only valid for the block

这会导致另一个问题:您试图在闭包中保留对 k 的引用,但是一旦 k 被 return 编辑,该引用就会失效功能。当项目按值移动时,它们的地址会改变,因此引用不再有效。

一个可能的解决方案是使用 Rc and RefCell:

fn filter<F>(&mut self, f: F) -> Rc<RefCell<Keeper>>
    where F: Fn() -> bool + 'static //'
{
    let mut k = Rc::new(RefCell::new(Keeper::new()));
    let k2 = k.clone();
    self.subscribe(move || {
        if f() { k2.borrow_mut().publish() }
    });
    k
}