存储 Fn 闭包的返回值

问题描述 投票:0回答:2

如果将

&dyn Fn(&mut [u8])
更改为
&dyn FnOnce(&mut [u8])
,则以下代码有效,因为这样
f
就可以安全移动。然而,我真的做不到
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
2个回答
1
投票

编译需要进行两处更改。一是把

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>

0
投票
use std::sync::Arc;

pub type OnVirtualTunWrite =
    Arc<dyn Fn(&dyn FnMut(&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: Fn(&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()
    }
}

Fn
以参考形式带来捕获的值。与T
FnMut
获取捕获的值作为可修改的参考。 &mutT
FnOnce
按原样获取捕获的值。 T

https://velog.io/@0xjuchan/Rust-Fn-FnMut-FnOnce

© www.soinside.com 2019 - 2024. All rights reserved.