gpt4 book ai didi

closures - 如何创建和使用回调函数列表?

转载 作者:行者123 更新时间:2023-11-29 08:14:49 25 4
gpt4 key购买 nike

在 Rust 中,我试图创建一个回调函数列表以供稍后调用:

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();
}
}

我主要听从建议 here on how to store a closure ,但是,我仍然看到一些错误:

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) {

……但这让我明白了:

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 最终将拥有闭包,因此需要借用它,我不完全确定。)

最佳答案

您的代码存在一些问题。这是一个完全固定的版本:

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必须限制在指定的生命周期内,并且为了将其存储在向量中,特征对象类型必须类似地受到限制,如 Box<FnMut() + 'a> .这样它们就可以匹配并确保内存安全,因此编译器可以通过。 -> ()的一部分 FnMut() -> ()顺便说一句,这是多余的。

需要进行的其余修复是插入一些 mut ;为了推送到向量,您自然需要一个可变引用,因此 &&mut更改,并为了对 calls 进行可变引用和 c必须进行绑定(bind) mut .

关于closures - 如何创建和使用回调函数列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28956195/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com