存储捕获返回值的闭包时存在冲突的生命周期要求
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 编辑,该引用就会失效功能。当项目按值移动时,它们的地址会改变,因此引用不再有效。
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
}
编辑:
我正在尝试在函数内创建一个闭包向量,向该向量添加一个标准闭包,然后 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 编辑,该引用就会失效功能。当项目按值移动时,它们的地址会改变,因此引用不再有效。
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
}