2014-03-26 60 views
5

我想使用boost::future延續和boost::when_all/boost::when_any使用boost :: future延續和boost :: when_all

升壓中繼 - 不是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(); 
} 

鏘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)...); 

我做它錯誤還是這是一個錯誤?

+0

我認爲你需要從'然後'而不是'f3'返回的'future',即'auto f4 = f3.then(...); f4.get();' – Casey

+0

沒有幫助:(https://gist.github.com/oberstet/9785088 – oberstet

+1

'when_all'需要迭代器,如果我閱讀了我找到的源代碼,你沒有使用迭代器。你嘗試把期貨放在一個向量中,並調用'when_all(vec.begin(),vec.end())'而不是? – stefan

回答

5

問題是隻能用右值futureshared_future調用when_all。從N3857

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

Requires:T is of type future<R> or shared_future<R> .

由於基準壓扁的規則,使左值導致T被推斷爲future<T>&違反規定的要求。 boost實現沒有檢查這個前提條件,所以你會在模板代碼中發現一個錯誤,在那裏應該是一個右值未來的轉移,變成一個左值未來的嘗試副本。

您需要可以移動期貨進入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的描述:

Postcondition:

  • The future object is moved to the parameter of the continuation function

  • valid() == false on original future object immediately after it returns

每30.6.6 [futures.unique_future/3:

The effect of calling any member function other than the destructor, the move-assignment operator, or valid on a future object for which valid() == false is undefined.

你可以避開大部分的C++ 14這些問題,避免命名期貨在所有:

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

啊是啊;)這裏是更多的小工具https://gist.github.com/oberstet/9785686 – oberstet

+0

我唯一想知道的是爲什麼我被允許移動未來兩次..請參閱上面鏈接的代碼。它將'f2'移動到'when_all'中,產生'f12',第二次移到'when_all'中,導致'f23'。你能解釋爲什麼允許/有效嗎?謝謝一堆! – oberstet

+1

@oberstet移動對象不是無效的,它處於「有效但未指定的狀態」。您可以重複移動對象,但這樣做的結果是實現定義的。 – Casey