首页 > 解决方案 > 存储 Fn 闭包的返回值

问题描述

&dyn Fn(&mut [u8])如果更改为,则下面的代码有效&dyn FnOnce(&mut [u8]),因为 thenf可以安全地移动。但是,我真的做不到,FnOnce因为我进一步发现了一些问题。Fn会工作。

但是,我真的需要捕获结果r并将其返回consume,如下所示

use std::sync::Arc;

pub type OnVirtualTunWrite = Arc<dyn Fn(&dyn Fn(&mut [u8]) , usize) -> Result<(), ()> + Send + Sync>;

struct A {
    on_virtual_tun_write: OnVirtualTunWrite
}

impl A {
    fn consume<R, F>(self, len: usize, f: F) -> Result<R,()>
    where
        F: FnOnce(&mut [u8]) ->  Result<R,()>,
    {
        let mut r: Option<Result<R,()>> = None;
        let result = (self.on_virtual_tun_write)(&|b: &mut [u8]| {
            r = Some(f(b));
        }, len);
        r.unwrap()
    }
}

我知道这样做Box<dyn FnOnce(&mut [u8])会起作用,但我试图避免动态分配。

有没有办法使这项工作?

标签: rust

解决方案


进行此编译需要进行两项更改。一种是F: FnOnce(&mut [u8])...consume()函数定义中更改为F: Fn(&mut [u8])... FnOnce() 类型的闭包在调用时会自行消耗,因此只能调用一次。

更改此设置将产生另一个r无法分配给闭包内部的错误。这是因为r它是一个来自闭包外部的捕获变量,而 Fn() 类型将不可变地借用捕获的变量。通过将第二个 Fn() 更改为 FnMut(),该r变量将被捕获为可变引用,因此可以从闭包内部分配:

Arc<dyn Fn(&dyn FnMut(&mut [u8]) , usize) -> Result<(), ()> + Send + Sync>

推荐阅读