这是我对how to create & use a list of callbacks的问题的跟进。
我试图创建(并在事件循环附近存储)一个回调函数列表,这些函数将在未来的某个不确定点调用。
struct ComplexThing {
calls: Vec<Box<FnMut()>>,
}
impl ComplexThing {
fn call<'a, T: FnMut() + 'a>(&'a mut self, func: T) {
self.calls.push(Box::new(func));
}
}
错误:
calls.rs:30:25: 30:39 error: the parameter type `T` may not live long enough [E0310]
calls.rs:30 self.calls.push(Box::new(func));
^~~~~~~~~~~~~~
calls.rs:30:39: 30:39 help: consider adding an explicit lifetime bound `T: 'static`...
calls.rs:30:25: 30:39 note: ...so that the type `T` will meet its required lifetime bounds
calls.rs:30 self.calls.push(Box::new(func));
^~~~~~~~~~~~~~
我尝试将其添加到struct
,修正了push
调用中有关生命周期的错误,
struct ComplexThing<'a> {
calls: Vec<Box<FnMut() + 'a>>,
}
impl ComplexThing {
fn call<'a, T: FnMut() + 'a>(&'a mut self, func: T) {
self.calls.push(Box::new(func));
}
}
......但是得到了我:
calls.rs:28:6: 28:18 error: wrong number of lifetime parameters: expected 1, found 0 [E0107]
calls.rs:28 impl ComplexThing {
^~~~~~~~~~~~
哪,是的,我认为结构有一个<'a>
,而我没有指定它。如果我添加它,
impl ComplexThing<'a> {
我明白了,
calls.rs:28:19: 28:21 error: use of undeclared lifetime name `'a` [E0261]
calls.rs:28 impl ComplexThing<'a> {
我不知道我是否应该在struct ComplexThing
上指定它。如果我把它关掉(我想我会更喜欢),
我认为有关Rust如何记录我未能到达的生命周期的事情至关重要。 FnMut
{目前}试图存储在ComplexThing
中的Box
是(在我的脑海中的设计中){em>拥有的实例{{1} }};它的生命周期应该小于ComplexThing
的生命周期 - 即,会发生以下两种情况之一:
.ComplexThing
的私有函数将最终从ComplexThing
移除Box<FnMut>
(因此取得其所有权),运行Vec
,然后退出,从而释放FnMut
。FnMut
已取消分配,在这种情况下,ComplexThing
和任何Vec
已取消分配。问题"How do I store a closure in Rust?"的答案让我觉得Box<FnMut>
不需要终身注释,但我得到的答案how to create & use a list of callbacks让我觉得我做了
我最好的猜测是Box<FnMut>
只是存储指向我并不真正拥有的对象的指针,我需要在堆上创建Box
的副本,或者在那里构建一个,然后该副本就是我可以拥有的副本。 (否则,如果它像堆栈上的闭包那样,我需要确保在FnMut
之前闭包没有超出范围,这就是为什么Rust让我注释生命。)
答案 0 :(得分:3)
'a
上的{p> ComplexThing
是一个通用的生命周期参数,需要定义与泛型类型参数一样多。如果您有struct Foo<T>
,则无法编写impl Foo<T>
,因为范围内没有具体类型T
;如果您希望它是通用的,则需要定义它impl<T> Foo<T>
。这也允许您编写约束,例如impl<T: Clone> Foo<T>
,只有在Foo<T>
是实现T
的类型的情况下才能在Clone
上实现方法。
那么,答案很简单,你需要将生命周期'a
定义为通用:
impl<'a> ComplexThing<'a> { … }