I was working on a project and I needed to put 2 async functions with the same signature in a vec, but everything I tried didn't work. Why can I not just store for example two references to the functions instead of having to use 20 Boxes just to end up with it not compiling again?
There is a slightly hacky way to with wrapper functions:
use futures::future::Future;
use std::pin::Pin;
async fn foo() -> i32 {
1
}
async fn bar() -> i32 {
2
}
fn foo_wrapper() -> Pin<Box<dyn Future<Output = i32>>> {
Box::pin(foo())
}
fn bar_wrapper() -> Pin<Box<dyn Future<Output = i32>>> {
Box::pin(bar())
}
#[tokio::main]
async fn main() {
let fns: Vec<&dyn Fn() -> Pin<Box<dyn Future<Output = i32>>>> =
vec![&foo_wrapper, &bar_wrapper];
assert_eq!((fns[0])().await, 1);
assert_eq!((fns[1])().await, 2);
}
Edit: a more generic wrapper function:
use futures::future::{BoxFuture, Future};
async fn foo() -> i32 {
1
}
async fn bar() -> i32 {
2
}
fn wrapper<T, F>(f: F) -> Box<dyn Fn() -> BoxFuture<'static, i32>>
where
T: Future<Output=i32> + Send + 'static,
F: Fn() -> T + 'static,
{
Box::new(move || Box::pin(f()))
}
#[tokio::main]
async fn main() {
let fns: Vec<Box<dyn Fn() -> BoxFuture<'static, i32>>> =
vec![wrapper(foo), wrapper(bar)];
assert_eq!((fns[0])().await, 1);
assert_eq!((fns[1])().await, 2);
}
The most straightforward/general way is to use something like Box<dyn Fn(Arguments…) -> BoxFuture<'static, Output>>
, though you might need to deal with lifetimes if the argument types are/use/contain references. Feel free to give more context to your concrete situation for more help. Also, the function will need to be converted into such a type, using a “wrapper future”, though if that’s a common need, a helper function can reduce some boilerplate to avoid the need to repeat the wrapping; feel free to ask more details on this point, too.
If what you are starting with are all function items, you could also use fn…
instead of Box<dyn Fn…>
.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.