@dakom for an answer illustrating this fact with examples, see Closures don't move? - #2 by Yandros
EDIT: actually you are the OP of that thread, so of course you already knew it
This is indeed the general pattern to make any 'static
closure be cheaply Clone
able (instead of giving Copy
-es of &f
, let's "give Clone
s of Rc::new(f)"). It should be noted, however, that Rc<impl Fn()> : !Fn()
, so a little trick is needed to get reference-counting cloning and the Fn()
callable interface:
use ::std::{
ops::Deref,
rc::Rc,
};
fn main ()
{
// non-Copy closure (it owns s: String which is not Copy)
let f = {
let s = String::from("Hello, World!");
move || {
println!("{}", s);
}
};
fn challenge (f1: impl Fn() + 'static, f2: impl Fn() + 'static)
{
f1();
f2();
}
// Attempt 1
// let at_f = &f;
// challenge(at_f, at_f); // Error, not 'static
// Attempt 2
// let at_f_static = Rc::new(f);
// challenge(at_f_static.clone(), at_f_static); // Error: Rc<_> does not impl Fn
let f = {
let at_f_static = Rc::new(f);
move || {
at_f_static.deref()()
}
};
challenge(f.clone(), f);
}