This crate provides a macro that makes all captures clone automatically.
Given this code snippet:
fn foo() {
let a = "a".to_string();
let _closure = move || {
println!("{}, a");
};
println!("{}, a");
}
You will get an error that a
was moved.
To fix it you can clone a
in a temporary scope:
fn foo() {
let a = "a".to_string();
let _closure = {
let a = a.clone();
move || {
println!("{}, a");
}
};
println!("{}, a");
}
Cloning can get tedious, clone-on-capture
macro can automatically generate that code for you:
#[clone_on_capture]
fn foo() {
let a = "a".to_string();
let _closure = move || {
println!("{}, a");
};
println!("{}, a");
}
This will also clone variables that implement Copy
, but it is not a problem as .clone()
is just an explicit way to do the same as Copy
.
https://doc.rust-lang.org/std/marker/trait.Copy.html#whats-the-difference-between-copy-and-clone
Use dc_
prefix to prevent variable from being cloned.
#[clone_on_capture]
fn do_not_clone_prefix() {
let dc_a = "a".to_string();
let dc_a_address = dc_a.as_ptr();
let closure = move || {
let b = dc_a;
let b_address = b.as_ptr();
assert_eq!(dc_a_address, b_address);
};
closure();
}
Capturing arguments in string-formatting macros doesn't work:
#[clone_on_capture]
fn foo() {
let a = "a".to_string();
let _closure = move || {
println!("{a}");
};
println!("{a}");
}