The code below works if &dyn Fn(&mut [u8])
is changed to &dyn FnOnce(&mut [u8])
, because then f
can be moved safely. However, I really can't make it FnOnce
because further I find some problems. Fn
would work.
However, I really need to capture the result r
and return it in consume
, like in below
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()
}
}
I know that making it Box<dyn FnOnce(&mut [u8])
would work but I'm trying to avoid dynamic allocation.
Is there a way to make this work?
There are two changes needed to make this compile. One is to change F: FnOnce(&mut [u8])...
in the consume()
function definition to F: Fn(&mut [u8])...
An FnOnce()-type closure will consume itself when called, so it can only be called once.
Changing this will give another error that r
cannot be assigned to inside the closure. This is because r
is a capture variable from outside the closure, and the Fn() type will borrow captured variables immutably. By changing the second Fn() to FnMut(), the r
variable will be captured as a mutable reference, and can therefore be assigned to from inside the closure:
Arc<dyn Fn(&dyn FnMut(&mut [u8]) , usize) -> Result<(), ()> + Send + Sync>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.