“无法移动 FnOnce 类型的值";移动盒装函数时 [英] "cannot move a value of type FnOnce" when moving a boxed function
问题描述
我正在尝试在 Rust 中进行一些更高阶的编程,但是我在处理闭包时遇到了一些困难.这是一个代码片段,说明了我遇到的问题之一:
I'm trying to do some higher order programming in Rust, but I'm having some difficulty dealing with closures. Here's a code snippet that illustrates one of the problems I'm having:
pub enum Foo {
Bar(Box<FnOnce(i32)>),
}
pub fn app(i: i32, arg: Foo) {
match arg {
Foo::Bar(f) => f(i),
}
}
当我编译这段代码时,我收到以下错误消息:
When I compile this piece of code I get the following error message:
error[E0161]: cannot move a value of type std::ops::FnOnce(i32) + 'static: the size of std::ops::FnOnce(i32) + 'static cannot be statically determined
--> src/main.rs:7:24
|
7 | Foo::Bar(f) => f(i),
| ^
因为我把函数放在一个Box
中,我以为这样可以解决编译器不知道大小的问题.我怎样才能使上述程序编译?
Since I put the function in a Box
, I would have thought that that would deal with the problem of the compiler not knowing the size. How can I make the above program compile?
推荐答案
这里是 FnOnce
trait 的定义(稍微简化了一点):
Here's the FnOnce
trait's definition (simplified a little):
pub trait FnOnce<Args> {
type Output;
fn call_once(self, args: Args) -> Self::Output;
}
要调用 FnOnce
闭包,您需要能够将闭包值本身移动到调用中.注意 self
必须是 actual 闭包类型;Box
是完全不同的类型.
To call a FnOnce
closure, you need to be able to move the closure value itself into the invocation. Note that self
has to be the actual closure type; a Box<dyn FnOnce>
is a different type altogether.
Box
现在可以被调用;您的原始代码按原样运行.
Box<dyn FnOnce>
is now able to be called; your original code works as-is.
在标准库中有一种类型可以解决这种情况:FnBox
.不幸的是,它不稳定.
There is a type in the standard library for working around this situation: FnBox
. Unfortunately, it's unstable.
您的替代选择是:
- 重构代码,以便保留实际闭包类型,而不是
Box
. - 改用
Box
. - 等待
FnBox
稳定. - 切换到夜间编译器.
- Refactor the code so that instead of
Box<FnOnce>
, you preserve the actual closure type. - Use
Box<FnMut>
instead. - Wait for
FnBox
to stabilise. - Switch to a nightly compiler.
这篇关于“无法移动 FnOnce 类型的值";移动盒装函数时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!