«Сглаживать» вложенные фьючерсы - PullRequest
2 голосов
/ 18 февраля 2012

У меня есть вспомогательная функция, которую я использую, чтобы «сплющить» вложенные фьючерсы в одно будущее:

РЕДАКТИРОВАТЬ: переименовано в «сворачивать» в «сплющить», как предложено.используя фьючерсы из библиотеки повышения:

template<typename T>
auto flatten(boost::unique_future<T>&& f) -> boost::unique_future<decltype(f.get().get())>
{
    auto shared_f = boost::shared_future<T>(std::move(f));
    return async(launch_policy::deferred, [=]() mutable
    {
        return shared_f.get().get();
    });
}

Используется так:

auto nested_future_result = async([]() -> boost::shared_future<int>
{
    auto tmp = async([]
    {
        return 1;
    });
    return boost::shared_future<int>(std::move(tmp));    
});

boost::unique_future<int> future_result = flatten(nested_future_result);
int result = future_result.get();

Проблема в том, что это работает, только если я преобразую «вложенное» будущее в shared_future.Есть ли хороший способ обойти это?Я хотел бы что-то вроде:

auto future_result = flatten(async([]
{
    return async([]
    {
        return 1;
    }); 
}));

int result = future_result.get();

Во-вторых, я немного не уверен в названии метода.Есть мнения?

1 Ответ

2 голосов
/ 18 февраля 2012

(Примечание: я не понимаю, как вы заставили boost::unique_future сотрудничать с std::async, поэтому я заменил все экземпляры boost::unique_future на std::future. Код был протестирован и работает на моем конце.)

Проблема заключается в том, что лямбда-выражения либо захватываются по значению (что на самом деле означает захват по копии), либо по ссылке (здесь не применимо, поскольку мы хотим связать время жизни с нашим замыканием), тогда как std::future - этодвигаться только.Ответ на этот вопрос обычно std::bind, хотя в этом случае std::async имеет встроенную bind -подобную функциональность:

template<typename T>
auto fold(std::future<T>&& f)
-> std::future<decltype(f.get().get())>
{
    return std::async(std::launch::deferred, [](std::future<T>&& f)
    {
        return f.get().get();
    }, std::move(f));
}

У меня нет хорошего имени, чтобы рекомендовать мне 'Боюсь.Если шаблон, возможно, работал рекурсивно для преобразования любого std::future<std::future<std::future<...std::future<T>...>>> в std::future<T>, тогда, возможно, я бы позвонил, если flatten_future.Или, может быть, просто flatten, поскольку в конце концов он принимает только std::future.


Предполагая, что у нас уже есть унарный async:

template<typename Functor, typename Arg, typename... Args>
auto async(Functor&& functor, Arg&& arg, Args&&.... args)
-> decltype( async(std::bind(std::forward<Functor>(functor)
    , std::forward<Arg>(arg), std::forward<Args>(args)...)) )
{
    return async(std::bind(std::forward<Functor>(functor)
        , std::forward<Arg>(arg), std::forward<Args>(args)...));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...