如何创建&使用回调函数列表? [英] How do I create & use a list of callback functions?

查看:140
本文介绍了如何创建&使用回调函数列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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.

这篇关于如何创建&amp;使用回调函数列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆