Использование границ времени жизни более высокого порядка для связанных типов - PullRequest
2 голосов
/ 29 февраля 2020

Я хотел бы создать функцию - давайте назовем ее foo. Я хотел бы, чтобы эта функция принимала параметр predicate, равный FnOnce Предикат принимает один параметр t - ссылка типа T. Предикат возвращает будущее, которое захватывает t время жизни.

Типичное значение predicate может выглядеть следующим образом: fn predicate<'a>(instance: &'a SomeType) -> Future<Output = ()> + 'a.

Хотя я могу достичь этого, используя границы времени жизни более высокого порядка и BoxFuture:

fn foo_boxed<T, E, R>(predicate: E)
where
    for<'a> E: FnOnce(&'a T) -> BoxFuture<'a, R> + Send + 'static,
    R: Send + 'static,
{
}

Я бы хотел добиться того же результата, используя только дженерики. Похоже, синтаксис for<'a> соответствует только ближайшему параметру, поэтому следующее не будет компилироваться:

fn foo_non_boxed_1<T, E, F>(predicate: E)
where
    for<'a> E: FnOnce(&'a T) -> F + Send + 'static,
    F: Future + Send + 'a, // 'a is undeclared here
    F::Output: Send + 'static,
{
}

Внутри foo Я хотел бы сохранить предикат для последующего использования и вызвать его из другого поток, передавая T.

Есть ли способ добиться этого?

1 Ответ

0 голосов
/ 01 марта 2020

Вам нужна дополнительная черта, чтобы обойти <Type as FnOnce(T) -> _>::Output, которая недействительна, но вот решение:

use std::future::Future;

trait MyFnOnce<T, O>: FnOnce(T) -> O {
    type Output;
}

impl<T, O, F> MyFnOnce<T, O> for F
where
    F: FnOnce(T) -> O,
{
    type Output = O;
}

fn foo_non_boxed_1<T, E, F>(predicate: E)
where
    E: for<'a> FnOnce(&'a T) -> F + Send + 'static,
    for<'a> <E as MyFnOnce<&'a T, F>>::Output: 'a,
    F: Future + Send,
    F::Output: Send + 'static,
{
}

В качестве альтернативы, для Nightly вам не нужна дополнительная черта, а два флажка функций:

#![feature(fn_traits, unboxed_closures)]

use std::future::Future;

fn foo_non_boxed_1<T, E, F>(predicate: E)
where
    E: for<'a> FnOnce(&'a T) -> F + Send + 'static,
    for<'a> <E as FnOnce<&'a T>>::Output: 'a,
    F: Future + Send,
    F::Output: Send + 'static,
{
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...