如何创建&使用回调函数列表? [英] How do I create & use a list of callback functions?
问题描述
在Rust中,我试图创建一个回调函数列表,稍后调用:
In Rust, I'm trying to create a list of callbacks functions to invoke later:
use std::vec::Vec;
fn add_to_vec<T: FnMut() -> ()>(v: &Vec<Box<FnMut() -> ()>>, f: T) {
v.push(Box::new(f));
}
fn call_b() {
println!("Call b.");
}
#[test]
fn it_works() {
let calls: Vec<Box<FnMut() -> ()>> = Vec::new();
add_to_vec(&calls, || { println!("Call a."); });
add_to_vec(&calls, call_b);
for c in calls.drain() {
c();
}
}
我主要是按照建议在这里如何存储封闭,但是,我仍然看到一些错误:
I'm mostly following the advice here on how to store a closure, however, I'm still seeing some errors:
src/lib.rs:6:12: 6:23 error: the parameter type `T` may not live long enough [E0311]
src/lib.rs:6 v.push(Box::new(f));
^~~~~~~~~~~
src/lib.rs:6:23: 6:23 help: consider adding an explicit lifetime bound for `T`
src/lib.rs:5:68: 7:2 note: the parameter type `T` must be valid for the anonymous lifetime #1 defined on the block at 5:67...
src/lib.rs:5 fn add_to_vec<T: FnMut() -> ()>(v: &Vec<Box<FnMut() -> ()>>, f: T) {
src/lib.rs:6 v.push(Box::new(f));
src/lib.rs:7 }
src/lib.rs:6:12: 6:23 note: ...so that the type `T` will meet its required lifetime bounds
src/lib.rs:6 v.push(Box::new(f));
^~~~~~~~~~~
函数签名:
fn add_to_vec<'a, T: FnMut() -> ()>(v: &Vec<Box<FnMut() -> ()>>, f: &'a T) {
...但这会得到我:
… but this gets me:
src/lib.rs:6:12: 6:23 error: the trait `core::ops::Fn<()>` is not implemented for the type `&T` [E0277]
src/lib.rs:6 v.push(Box::new(f));
^~~~~~~~~~~
error: aborting due to previous error
src/lib.rs:6:12: 6:23 error: the trait `core::ops::Fn<()>` is not implemented for the type `&T` [E0277]
src/lib.rs:6 v.push(Box::new(f));
^~~~~~~~~~~
src/lib.rs:18:24: 18:51 error: mismatched types:
expected `&_`,
found `[closure src/lib.rs:18:24: 18:51]`
(expected &-ptr,
found closure) [E0308]
src/lib.rs:18 add_to_vec(&calls, || { println!("Call a."); });
^~~~~~~~~~~~~~~~~~~~~~~~~~~
(最后一个错误可以通过添加&
来纠正;而我认为这是我需要的,因为 add_to_vec
将最终拥有闭包,因此需要借用它,我不完全确定。)
(The last error I can correct by adding a &
; while I think this is something I should need, because add_to_vec
is going to end up owning the closure, and thus needs to borrow it, I'm not entirely sure.)
推荐答案
您的代码有一些问题。这是一个完全固定的版本开头:
There are a few problems with your code. Here’s a fully fixed version to begin with:
use std::vec::Vec;
fn add_to_vec<'a, T: FnMut() + 'a>(v: &mut Vec<Box<FnMut() + 'a>>, f: T) {
v.push(Box::new(f));
}
fn call_b() {
println!("Call b.");
}
#[test]
fn it_works() {
let mut calls: Vec<Box<FnMut()>> = Vec::new();
add_to_vec(&mut calls, || { println!("Call a."); });
add_to_vec(&mut calls, call_b);
for mut c in calls.drain() {
c();
}
}
生命周期问题是,共同基本寿命;如果你只写通用约束 T:FnMut()
,它假设只需要存活,只要函数调用不再。因此,需要向它添加两个东西:通用参数 T
必须约束到指定的生命周期,为了将其存储在向量中,trait对象类型必须类似地被约束为 Box
。这样他们都匹配,并确保内存安全,所以编译器让它通过。 - > ()
的一部分FnMut() - > ()
是多余的。
The lifetime issue is that the boxed function objects must have a common base lifetime; if you just write the generic constraint T: FnMut()
, it is assumed to only need to live as long as the function call and not any longer. Therefore two things need to be added to it all: the generic parameter T
must be constrained to a specified lifetime, and in order to store it inside the vector, the trait object type must similarly be constrained, as Box<FnMut() + 'a>
. That way they both match up and memory safety is ensured and so the compiler lets it through. The -> ()
part of FnMut() -> ()
is superfluous, by the way.
需要做的其余修复是插入一些 mut
;为了推送向量,你自然需要一个可变的引用,因此&
到& mut
更改,并且为了对调用
和 c
进行可变引用,必须将绑定设置为 mut
。
The remaining fixes that need to be made are the insertion of a few mut
; in order to push to the vector, you naturally need a mutable reference, hence the &
to &mut
changes, and in order to take mutable references to calls
and c
the bindings must be made mut
.
这篇关于如何创建&使用回调函数列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!