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

时间:2014-03-26 14:36:26

标签: c++ c++11 boost future continuations

我想将boost::future与延续boost::when_all / boost::when_any一起使用。

Boost trunk - 不是1.55 - 包括后者的实现(以提案here为模型,即将推出C ++ 14/17和Boost 1.56)。

This就是我所拥有的(它不会编译):

#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用this纾困 - 这是一段摘录:

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

我做错了还是这个错误?

1 个答案:

答案 0 :(得分:6)

问题是只能使用右值when_allfuture调用shared_future。来自N3857

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

要求: T的类型为future<R>shared_future<R>

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

您需要将期货移至when_all参数:

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

或者首先避免命名它们:

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

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

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

done.get();

因为您调用then的未来将被移动到延续的参数中。来自N3857中then的描述:

  

后置条件:

     
      
  • 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();