考虑以下Rust代码:
use std::future::Future;
use std::pin::Pin;
fn main() {
let mut v: Vec<_> = Vec::new();
for _ in 1..10 {
v.push(wrap_future(Box::pin(async {})));
}
}
fn wrap_future<T>(a: Pin<Box<dyn Future<Output=T>>>) -> impl Future<Output=T> {
async {
println!("doing stuff before awaiting");
let result=a.await;
println!("doing stuff after awaiting");
result
}
}
正如您所看到的,我放入Vec
的期货不需要装箱,因为它们都是相同的类型,编译器可以推断出该类型是什么。
我想创建一个struct
,该Vec<...>
类型作为其成员之一,以便我可以在main()
末尾添加一行:
let thing = MyStruct {myvec: v};
没有任何额外的开销(即装箱)。
类型推断和impl Trait
语法在结构成员上是不允许的,并且由于异步块返回的未来类型完全存在于编译器中,并且对该异步块是排他的,因此无法通过名称引用它。在我看来,我想做的事是不可能的。是吗?如果是这样,它会在Rust的未来版本中成为可能吗?
我知道,像我对wrap_future()
的论证那样,简单地把所有的期货都装在Vec
中,可以很容易地回避这个问题,但如果我能避免的话,我宁愿不这样做。
我很清楚,这样做意味着在我的整个代码库中可能只有一个async
块,其结果值可能被添加到这样的Vec
中,因此在我的整个代码库中可能只有一个函数可以创建可能被推入的值。我可以接受这个限制。
没关系,我很笨。我忘了结构体可以有类型参数。
struct MyStruct<F> where F: Future<Output=()> {
myvec: Vec<F>,
}