Использование boost :: future с продолжениями и boost :: when_all

Я хотел бы использовать boost::future с продолжениями и boost::when_all / boost::when_any,

Увеличение хобот — не 1.55 — включает реализации для последнего (смоделировано после предложения Вот, готовится к выпуску C ++ 14/17 и Boost 1.56).

это это то, что у меня есть (и не компилируется):

#include <iostream>

#define BOOST_THREAD_PROVIDES_FUTURE
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
#define BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY
#include <boost/thread/future.hpp>

using namespace boost;

int main() {
future<int> f1 = async([]() { return 1; });
future<int> f2 = async([]() { return 2; });

auto f3 = when_all(f1, f2);

f3.then([](decltype(f3)) {
std::cout << "done" << std::endl;
});

f3.get();
}

Clang 3.4 выручает с этот — вот выдержка:

/usr/include/c++/v1/memory:1685:31: error: call to deleted constructor of 'boost::future<int>'
::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);

Я делаю это неправильно или это ошибка?

6

Решение

Проблема в том, что when_all может вызываться только с помощью rvalue future или же shared_future, От N3857:

template <typename... T>
see below when_all(T&&... futures);

Требуется: T имеет тип future<R> или же shared_future<R>,

Благодаря правилам свертывания ссылок передача lvalue приводит к T выводится future<T>& в нарушение заявленного требования. Реализация boost не проверяет это предварительное условие, поэтому вы глубоко в коде шаблона получаете ошибку, при которой то, что должно быть перемещением rvalue-будущего, превращается в попытку копирования lvalue-будущего.

Вы должны либо переместить фьючерс в when_all параметры:

auto f3 = when_all(std::move(f1), std::move(f2));

или не называйте их в первую очередь:

auto f = when_all(async([]{return 1;}),
async([]{return 2;}));

Кроме того, вы должны get будущее вернулось из then вместо промежуточного будущего:

auto done = f.then([](decltype(f)) {
std::cout << "done" << std::endl;
});

done.get();

так как будущее, на которое вы звоните then перемещается в параметр продолжения. Из описания then в N3857:

Постусловие:

  • future объект перемещается в параметр функции продолжения

  • valid() == false на оригинале future объект сразу после его возвращения

Согласно 30.6.6 [futures.unique_future] / 3:

Эффект вызова любой функции-члена, кроме деструктора, оператора присваивания или valid на future объект для которого valid() == false не определено

Вы можете избежать большинства этих проблем в C ++ 14, вообще не называя фьючерсы:

when_all(
async([]{return 1;}),
async([]{return 2;})
).then([](auto&) {
std::cout << "done" << std::endl;
}).get();
6

Другие решения

Других решений пока нет …