0

对于背景上下文:我正在创建一个基于观察者/订阅者的全局事件系统(使用单个共享事件系统)。我决定FnMut用作我的回调闭包。'a放置在impl临时结构的生存期Data<'a>应该允许callback方法中的参数mut_func()与整个Data结构一样长。因为callback参数使用了F肯定受生命周期约束的泛型'a。但是错误仍然出现,表明callback参数的寿命不够长。

我最初用作Box<T>的容器dyn FnMut(u32),但Box<T>需要回调'static(因为我将装箱的泛型转换为盒子特征对象),这在我的场景中是无法实现的(为了可读性)。然后我尝试使用Rc<RefCell<T>>which 可悲的是不支持 trait 对象。

另外,我使用泛型作为callback参数,因为我希望该函数具有更高的可读性,而不是必须看到Box<T>环绕无处不在的整个闭包,因为这个事件系统是我程序的核心部分。我将尽一切努力使“前端”更具可读性和更清晰(除了显着的性能影响)。

注意:这是我的示例程序。如果需要,我可以发布实际程序。

错误:

error[E0597]: `callback` does not live long enough
>  | impl<'a> Data<'a> {  
>  |      -- lifetime `'a` defined here  
>  |     fn mut_func<F: FnMut(u32) -> () + 'a>(&mut self, mut callback: F) {  
>  |         self.o.push(&mut callback as &mut dyn FnMut(u32) -> ());  
>  |         ------------^^^^^^^^^^^^^------------------------------  
>  |         |           |  
>  |         |           borrowed value does not live long enough  
>  |         argument requires that `callback` is borrowed for `'a`  
>  |     }  
>  |     - `callback` dropped here while still borrowed  

例子:

use std::any::Any;
use std::mem;
use std::rc::Rc;
use std::cell::RefCell;

struct Event<'a> {
    obs: Vec<&'a mut dyn FnMut(u32) -> ()>,
}

impl<'a> Event<'a> {
    fn subscriber<F: FnMut(u32) -> () + 'a>(&mut self, mut callback: F) {
        self.o.push(&mut callback as &mut dyn FnMut(u32) -> ());
    }
}

fn main () {
    let mut e = Event {obs: Vec::new()};
    let x = 3;
    e.subscriber(|n| {x+n;});
}
4

1 回答 1

2

callback参数使用F绝对受生命周期约束的泛型'a。但是错误仍然出现,表明callback参数的寿命不够长。

callback寿命足够长,但问题是您没有存储callback收到的数据,而是将其存储为转换为特征对象( dyn) 并且该特征对象的数据必须归某物所有。

我最初用作Box<T>的容器dyn FnMut(u32),但Box<T>需要回调'static

不,它没有。这编译:

struct Event<'a> {
    obs: Vec<Box<dyn FnMut(u32) -> () + 'a>>,
}

impl<'a> Event<'a> {
    fn subscriber<F: FnMut(u32) -> () + 'a>(&mut self, callback: F) {
        self.obs.push(Box::new(callback));
    }
}

然后再进行一项更改,您的示例将编译:x之前定义,e因此x寿命长于e

fn main() {
    let x = 3;
    let mut e = Event {obs: Vec::new()};
    e.subscriber(|n| {x+n;});
}

锈游乐场副本

于 2020-09-30T04:20:27.780 回答