假设我们有这样的代码:
fn inc(src: u32) -> u32 {
src + 1
}
fn inc2(src: u32) -> u32 {
src + 2
}
type Incrementer = fn(u32) -> u32;
fn increment_printer(inc: Incrementer) {
println!("{}", inc(1));
}
fn main() {
increment_printer(inc);
increment_printer(inc2);
}
Run Code Online (Sandbox Code Playgroud)
两个函数具有相同的签名,第三个函数接受它们的指针。运行此代码会打印 2\n3。
但类似的东西不会编译:
use core::future::Future;
async fn inc(src: u32) -> u32 {
src + 1
}
async fn inc2(src: u32) -> u32 {
src + 2
}
type Incrementer = fn(u32) -> dyn Future<Output = u32>;
async fn increment_printer(inc: Incrementer) {
println!("{}", inc(1).await);
}
fn main() {
async {
increment_printer(inc).await;
increment_printer(inc2).await;
}
}
Run Code Online (Sandbox Code Playgroud)
18 | increment_printer(inc).await;
| ^^^ expected trait object `dyn Future`, found opaque type
|
= note: expected fn pointer `fn(_) -> (dyn Future<Output = u32> + 'static)`
found fn item `fn(_) -> impl Future {inc}`
Run Code Online (Sandbox Code Playgroud)
我知道每个异步函数都有自己的类型,如错误中所述。是否可以强制编译器忘记具体类型并将它们视为相似类型?
也许可以强制异步函数返回Box<Future<Output=u32>>
?
我不想为了方便而放弃异步函数。另外,我不想在将异步函数指针传递给函数之前要求调用 Box::pin() 。
知道是否有更多选择会很有趣。
也许可以强制异步函数返回 Box<Future<Output=u32>> ?
不是真的,但可以将函数包装到一个调用该函数并返回一个装箱的 future 的闭包中。当然,闭包本身需要装箱,以便像这样的函数increment_printer
可以接收它,但这两种装箱都可以封装在实用函数中。例如(游乐场):
use core::future::Future;
use std::pin::Pin;
async fn inc(src: u32) -> u32 {
src + 1
}
async fn inc2(src: u32) -> u32 {
src + 2
}
type Incrementer = Box<dyn FnOnce(u32) -> Pin<Box<dyn Future<Output = u32>>>>;
fn force_boxed<T>(f: fn(u32) -> T) -> Incrementer
where
T: Future<Output = u32> + 'static,
{
Box::new(move |n| Box::pin(f(n)))
}
async fn increment_printer(inc: Incrementer) {
println!("{}", inc(1).await);
}
fn main() {
async {
increment_printer(force_boxed(inc)).await;
increment_printer(force_boxed(inc2)).await;
};
}
Run Code Online (Sandbox Code Playgroud)
如果你有能力制作像increment_printer
泛型这样的函数,那么你就可以摆脱外框(playground):
// emulate trait alias
trait Incrementer: FnOnce(u32) -> Pin<Box<dyn Future<Output = u32>>> {}
impl<T> Incrementer for T
where T: FnOnce(u32) -> Pin<Box<dyn Future<Output = u32>>>
{
}
fn force_boxed<T>(f: fn(u32) -> T) -> impl Incrementer
where
T: Future<Output = u32> + 'static,
{
move |n| Box::pin(f(n)) as _
}
async fn increment_printer(inc: impl Incrementer) {
println!("{}", inc(1).await);
}
Run Code Online (Sandbox Code Playgroud)
我不想为了方便而放弃异步函数。另外,我不想
Box::pin()
在将异步函数指针传递给函数之前要求调用。
您需要Box::pin()
在某个地方进行调用- 上面的调用至少限于一个地方,并且您会得到一种Incrementer
类型,就像异步函数的接收者通过force_boxed()
.
归档时间: |
|
查看次数: |
4277 次 |
最近记录: |