Як використовувати fust async fn, який приймає посилання як зворотний дзвінок?


10

async fnповертає анонімний тип, який реалізується Future, тому, якщо ми хочемо використовувати його як зворотний виклик, нам потрібно перетворити повернене значення в об’єкт ознаки.

Я намагався написати функцію для цього, але у мене були деякі проблеми з життям.

async fnповерне термін служби всіх параметрів, тому підпис зворотного дзвінка також повинен. Як я можу додати термін експлуатації до зворотного значення зворотного дзвінка?

use futures::future::{Future, FutureExt, LocalBoxFuture};

type Context = ();
type AsyncCb = Box<dyn for<'r> FnOnce(&'r Context) -> LocalBoxFuture<'r, ()>>;

fn normalize_async_cb<Fut: Future<Output = ()>>(f: for<'r> fn(&'r Context) -> Fut) -> AsyncCb
//                                                    how to add 'r for Fut?  ^^^
{
    let cb = move |ctx: &Context| f(ctx).boxed_local();
    Box::new(cb)
}

Чому вхід до normalize_async_cbфункції покажчика?
Coder-256

Також, що ви маєте на увазі під "зворотним дзвоном"? Чи можете ви навести приклад, де показано, де вам потрібен такий тип зворотного виклику?
Coder-256

Відповіді:


1

Іржа не підтримує поліморфізм вищого типу, тому вам потрібно додати параметр "довічний" до AsyncCbтипу:

use futures::future::{Future, FutureExt, LocalBoxFuture};

type Context = ();
type AsyncCb<'r> = Box<dyn FnOnce(&'r Context) -> LocalBoxFuture<'r, ()> + 'r>;

fn normalize_async_cb<'r, Fut: Future<Output = ()> + 'r>(f: fn(&'r Context) -> Fut) -> AsyncCb {
    let cb = move |ctx: &'r Context| f(ctx).boxed_local();
    Box::new(cb)
}

Крім того, ви можете уникнути Box, повернувши implознаку:

fn normalize_async_cb<'r, Fut: Future<Output = ()> + 'r>(
    f: fn(&'r Context) -> Fut,
) -> impl FnOnce(&'r Context) -> LocalBoxFuture<'r, ()> {
    let cb = move |ctx: &'r Context| f(ctx).boxed_local();
    cb
}

(Тоді, хто телефонує, за бажанням може використовувати Box::new(normalize_async_cb(…))як тип AsyncCb.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.