如何在Rust中将异步函数放入地图中?

hyper编写异步路由器时,我无法处理异步功能。

此代码:

use std::collections::HashMap;
use std::future::Future;

type BoxedResult<T> = Result<T,Box<dyn std::error::Error + Send + Sync>>;
type CalcFn = Box<dyn Fn(i32,i32) -> dyn Future<Output = BoxedResult<i32>>>;

async fn add(a: i32,b: i32) -> BoxedResult<i32> {
    Ok(a + b)
}

async fn sub(a: i32,b: i32) -> BoxedResult<i32> {
    Ok(a - b)
}

fn main() {
    let mut map: HashMap<&str,CalcFn> = Default::default();
    map.insert("add",Box::new(add));
    map.insert("sub",Box::new(sub));

    println!("map size: {}",map.len());
}

生成以下编译器错误:

error[E0271]: type mismatch resolving `<fn(i32,i32) -> impl std::future::Future {add} as std::ops::FnOnce<(i32,i32)>>::Output == dyn std::future::Future<Output = std::result::Result<i32,std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
  --> src/main.rs:17:23
   |
17 |     map.insert("add",Box::new(add));
   |                       ^^^^^^^^^^^^^ expected opaque type,found trait std::future::Future
   |
   = note: expected type `impl std::future::Future`
              found type `dyn std::future::Future<Output = std::result::Result<i32,std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
   = note: required for the cast to the object type `dyn std::ops::Fn(i32,i32) -> dyn std::future::Future<Output = std::result::Result<i32,std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`

error[E0271]: type mismatch resolving `<fn(i32,i32) -> impl std::future::Future {sub} as std::ops::FnOnce<(i32,std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
  --> src/main.rs:18:23
   |
18 |     map.insert("sub",Box::new(sub));
   |                       ^^^^^^^^^^^^^ expected opaque type,std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`

impl Futuredyn Future之间似乎存在冲突,但我不知道如何处理。

holylai 回答:如何在Rust中将异步函数放入地图中?

之所以会这样,是因为impl Future是一种具体的唯一类型,而dyn Future是一种抽象类型。 HashMap期望抽象类型,因为它只能容纳单个类型的实例。

如果我们可以将异步函数的返回类型装箱,则可以将这些期货添加到HashMap中。

首先,我们需要更改CalcFn的类型:

type CalcFn = Box<dyn Fn(i32,i32) -> Pin<Box<dyn Future<Output = i32>>>>;

这可以解决问题:

let mut map: HashMap<&str,CalcFn> = Default::default();
map.insert("add",Box::new(|a,b| Box::pin(add(a,b))));
map.insert("sub",b| Box::pin(sub(a,b))));

println!("map size: {}",map.len());

//map.get("add").unwrap()(2,3).await

complete example  简化的Future的{​​{1}}类型,使用Item而不是i32。另请检查full code for your case

本文链接:https://www.f2er.com/3162341.html

大家都在问