Consider the following:
use std::ops::Fn;
fn require_picky_callback( cb : impl Fn() -> () + 'static) { }
fn main() {
let s = String::from("Rust");
...
let s_copy = s.clone();
let cb = move || {
s_copy;
};
require_picky_callback(cb);
}
If String in this example were replaced with a Copy-able type such as int, this example would compile. Unfortunately since capture by Clone is not possible, the only workaround is to create a copy outside the closure and move it in, but then the closure is no longer a pure function Fn, and instead a FnOnce. Is there any workaround such that my closure remains a Fn but also captures the String? This seems like it should be possible in principal.
Note that this RFC where the inability to clone into closure issue is discussed has a similar example, but less restrictive since the thread::spawn function does not require Fn
>Solution :
Easy, just make a copy for each invocation and thus don’t move the String out of the closure:
fn require_picky_callback(_cb: impl Fn() -> () + 'static) {}
fn main() {
let s = String::from("Rust");
let cb = move || {
let s = s.clone();
drop(s);
};
require_picky_callback(cb);
}
This works because while s is captured by the closure, but because clone only requires a reference it’s never moved out of.
The drop is only there to show we can do anything we want with the new s it’s not required at all.