How do to put two closures with the same definition into a Vec
?
Here is a minimal reproducible example:
fn main() {
let mut vec = Vec::new();
vec.push(Box::new(|| println!("test")));
vec.push(Box::new(|| println!("test2")));
vec.iter().for_each(|f| (f)());
}
Which failed on compiling with following error:
error[E0308]: mismatched types
--> src/main.rs:4:23
|
3 | vec.push(Box::new(|| println!("test")));
| -- the expected closure
4 | vec.push(Box::new(|| println!("test2")));
| -------- ^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
| |
| arguments to this function are incorrect
|
= note: expected closure `[closure@src/main.rs:3:23: 3:25]`
found closure `[closure@src/main.rs:4:23: 4:25]`
= note: no two closures, even if identical, have the same type
= help: consider boxing your closure and/or using it as a trait object
You must explicitly tell that vec
holds boxed trait objects:
fn main() {
let mut vec: Vec<Box<dyn Fn()>> = Vec::new();
vec.push(Box::new(|| println!("test")));
vec.push(Box::new(|| println!("test2")));
vec.iter().for_each(|f| (f)());
}
On the other hand you can leave it as it and "cast" boxed object with as
keyword:
fn main() {
let mut vec = Vec::new();
vec.push(Box::new(|| println!("test")) as Box<dyn Fn()>);
vec.push(Box::new(|| println!("test2")));
vec.iter().for_each(|f| (f)());
}
note that you have to do it only once, since now rust will infer that type of vec
is indeed Vec<Box<dyn Fn()>>
, and further pushing will know to do this cast automatically.