移动盒装函数时"无法移动FnOnce类型的值"

sve*_*son 10 rust

我正在尝试在Rust中进行一些高阶编程,但是我在处理闭包时遇到了一些困难.这是一个代码片段,说明了我遇到的一个问题:

pub enum Foo {
    Bar(Box<FnOnce(i32)>),
}

pub fn app(i: i32, arg: Foo) {
    match arg {
        Foo::Bar(f) => f(i),
    }
}
Run Code Online (Sandbox Code Playgroud)

当我编译这段代码时,我收到以下错误消息:

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),
  |                        ^
Run Code Online (Sandbox Code Playgroud)

因为我把函数放在一个Box,我会想到这将解决编译器不知道大小的问题.如何编译上述程序?

DK.*_*DK. 14

这是FnOnce特质的定义(简化了一点):

pub trait FnOnce<Args> {
    type Output;

    fn call_once(self, args: Args) -> Self::Output;
}
Run Code Online (Sandbox Code Playgroud)

要调用FnOnce闭包,您需要能够将闭包值本身移动到调用中.注意,self必须是实际的闭包类型; a Box<dyn FnOnce>是完全不同的类型.

结果,这或多或少是不可能的.

现在,为处理的只是这种情况在标准库类型:Box<dyn FnOnce>. 不幸的是,它最近才被添加,因此不能用于稳定的Rust(那是"或更少"部分).

所以,你的选择是:

  • 重构代码,以便FnBox保留实际的闭包类型.
  • Box<FnOnce>改用.
  • 等待Box<FnMut>稳定.
  • 切换到夜间编译器.