【问题标题】:How to pass a closure via dynamic dispatch in an object-safe method?如何通过对象安全方法中的动态调度传递闭包?
【发布时间】:2020-04-04 02:57:45
【问题描述】:
如何将闭包传递给对象安全的 trait 方法或通过动态调度?
我有 answered this myself,但答案有些不足:FnOnce 闭包必须装箱,因为它们没有大小,必须在使用时消耗(因此不能通过引用传递)。
【问题讨论】:
-
-
-
您在问什么还不清楚。你提供的代码compiles fine——你到底想用它来演示什么?您是否在问是否有某种方法可以通过动态调度传递 FnOnce 闭包而不使用 Box(并且可能不会使用另一种堆分配)?
标签:
rust
closures
traits
trait-objects
【解决方案1】:
不用Box也可以通过:
fn pass_fn_once(do_thing: &dyn FnOnce()) {
//do_thing();
}
fn main() {
pass_fn_once(&|| println!("Hello!"));
}
但是,您将无法在pass_fn_once 中实际调用do_thing,因为它只是借用的 - calling an FnOnce consumes it。
如果他们是Boxed,您可以确定pass_fn_once 拥有所有权,以便之后可以丢弃闭包。
【解决方案2】:
Fn 和 FnMut 闭包可以通过引用传递,如下所示。 FnOnce 可以通过引用传递,但不能调用,除非它是拥有,例如通过Box。
fn pass_fn(get_num: &dyn Fn() -> i32) {
let _num = get_num();
}
fn pass_fn_mut(set_num: &mut dyn FnMut(i32)) {
set_num(6);
}
fn pass_fn_once(do_thing: Box<dyn FnOnce()>) {
do_thing();
}
fn main() {
pass_fn(&|| 2);
let mut x = 1;
pass_fn_mut(&mut |y| x = y);
pass_fn_once(Box::new(|| println!("Hello!")));
}