MrN*_*sco 11 closures lifetime rust
当我尝试编译以下代码时:
fn main() {
(...)
let mut should_end = false;
let mut input = Input::new(ctx);
input.add_handler(Box::new(|evt| {
match evt {
&Event::Quit{..} => {
should_end = true;
}
_ => {}
}
}));
while !should_end {
input.handle();
}
}
pub struct Input {
handlers: Vec<Box<FnMut(i32)>>,
}
impl Input {
pub fn new() -> Self {
Input {handlers: Vec::new()}
}
pub fn handle(&mut self) {
for a in vec![21,0,3,12,1] {
for handler in &mut self.handlers {
handler(a);
}
}
}
pub fn add_handler(&mut self, handler: Box<FnMut(i32)>) {
self.handlers.push(handler);
}
}
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
error: closure may outlive the current function, but it borrows `should_end`, which is owned by the current function
Run Code Online (Sandbox Code Playgroud)
我不能简单地添加move到闭包中,因为我需要should_end稍后在主循环中使用.我的意思是,我能,但由于bool是Copy,它只会影响到should_end瓶盖内,因而程序永远循环.
据我所知,由于input是在main函数中创建的,并且闭包存储在其中input,因此它不可能比当前函数寿命更长.有没有办法向Rust表达封闭不会比生命更长main?或者有可能我看不到关闭会比活动更长久main吗?在后一种情况下,有没有办法强迫它只活main?
我是否需要重构我处理输入的方式,或者是否有某些方法可以使其工作.如果我需要重构,我在哪里可以看到Rust的一个很好的例子?
这是一个简化版的围栏.我可能在其中犯了一个可能导致浏览器崩溃的错误.我碰巧遇到过一次,所以,要小心.
oli*_*obk 10
问题不是你的关闭,而是add_handler方法.完全展开它看起来像这样:
fn add_handler<'a>(&'a mut self, handler: Box<FnMut(i32) + 'static>)
Run Code Online (Sandbox Code Playgroud)
如您所见,'static特征对象存在隐式约束.显然我们不希望这样,所以我们引入第二个生命周期'b:
fn add_handler<'a, 'b: 'a>(&'a mut self, handler: Box<FnMut(i32) + 'b>)
Run Code Online (Sandbox Code Playgroud)
由于您handler要将对象添加到Input::handlers字段中,因此该字段不能超过handler对象的范围.因此,我们还需要限制其寿命:
pub struct Input<'a> {
handlers: Vec<Box<FnMut(i32) + 'a>>,
}
Run Code Online (Sandbox Code Playgroud)
这再次要求impl具有生命周期,我们可以在该add_handler方法中使用.
impl<'a> Input<'a> {
...
pub fn add_handler(&mut self, handler: Box<FnMut(i32) + 'a>) {
self.handlers.push(handler);
}
}
Run Code Online (Sandbox Code Playgroud)
现在剩下的就是使用a Cell来控制对你的should_end旗帜的访问.