c++ - std::async variant which works over a collection -
using std::async wondering whether possible have helper function, creates std::futures collection (one future every collection element).
often have following situation:
auto func = []( decltype(collection)::reference value ) { //some async work }; typedef std::result_of<decltype(func)>::type resulttype; std::vector<std::future<resulttype>> futures; futures.reserve(collection.size()); // create futures for( auto& element : collection ) { futures.push_back(std::async(func, element)); } // wait till futures done for( auto& future : futures ) { future.wait(); } to able reuse came following partial code:
template< class function, class ct, class... args> std::vector<std::future<typename std::result_of<function(args...)>::type>> async_all( function&& f, ct& col ) { typedef typename std::result_of<function(args...)>::type resulttype; std::vector<std::future<resulttype>> futures; futures.reserve(collection.size()); for( auto& element : collection ) { futures.push_back(std::async(func, element)); } } return futures; now have solve args problem, since in async_all, args cannot deduced anymore. thing can think of functor, converts element in collection args. there more elegant solution this?
you're there. collection passed async_all has information need uniquely determine function argument type; question how extract information. using auto keyword in function signature, can write return type after function arguments. not produces cleaner signature, lets use argument values decltype in deducing return types. instance:
template<typename f, typename ct> auto reduce(f f, ct coll) -> decltype(f(*begin(coll), *begin(coll)); of course, there other ways determine argument types provided functions (using function signature deduction templates). however, these approaches can fail cases involving overloaded functions and/or templated function objects.
the following code compiles , runs (prints "x=1" 10 times) under gcc 4.8 (earlier versions should work fine). notice how don't have explicitly mention std::future: can use decltype directly on std::async statement deduce it's type.
#include <future> #include <vector> #include <iostream> template<class function, class ct> auto async_all(function f, ct col) -> std::vector<decltype(std::async(f, *std::begin(col)))> { std::vector<decltype(std::async(f, *std::begin(col)))> futures; futures.reserve(col.size()); (auto& element : col) { futures.push_back(std::async(f, element)); } return futures; } int main() { using namespace std; (auto& f : async_all([](int x) { cout << "x = " << x << endl; }, vector<int>(10, 1))) f.get(); } (async_all evaluated once here, spec guarantees range expressions in range-based loops)
Comments
Post a Comment