使用boost :: future with continuations和boost :: when_all

obe*_*tet 6 c++ continuations boost future c++11

我想使用boost::futurecontinuation和boost::when_all/ boost::when_any.

Boost 主干 - 不是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();
}
Run Code Online (Sandbox Code Playgroud)

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)...);
Run Code Online (Sandbox Code Playgroud)

我做错了还是这个错误?

Cas*_*sey 6

问题是when_all只能用rvalue future或者调用shared_future.从N3857:

template <typename... T> 
see below when_all(T&&... futures); 
Run Code Online (Sandbox Code Playgroud)

要求: T是类型future<R>shared_future<R>.

由于参考折叠规则,传递左值导致T推断future<T>&违反规定的要求.boost实现不会检查这个前提条件,因此您在模板代码中得到一个错误,其中rvalue future的移动应该转变为左值未来的尝试副本.

您需要将期货移动到when_all参数中:

auto f3 = when_all(std::move(f1), std::move(f2));
Run Code Online (Sandbox Code Playgroud)

或者首先避免命名它们:

auto f = when_all(async([]{return 1;}),
                  async([]{return 2;}));
Run Code Online (Sandbox Code Playgroud)

此外,您必须getthen中间而不是中间的未来返回:

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

done.get();
Run Code Online (Sandbox Code Playgroud)

因为您调用的未来将then移动到延续的参数中.从thenN3857中的描述:

后置条件:

  • future对象被移动到延续函数的参数

  • valid() == false在原始future对象返回后立即返回

每30.6.6 [futures.unique_future]/3:

调用析构函数,移动赋值运算符以外的任何成员函数或未定义validfuture对象的效果valid() == false.

你可以通过避免命名期货来避免c ++ 14中的大多数问题:

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