std :: async变体,它处理集合 [英] std::async variant which works over a collection
问题描述
使用 std :: async
我想知道是否可能有一个帮助函数,它创建 std :: future $ c
Using std::async
I was wondering whether it is possible to have a helper function, which creates std::future
s from a collection (one future for every collection element).
通常我有以下情况:
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 all futures
for( auto& element : collection ) {
futures.push_back(std::async(func, element));
}
// Wait till futures are done
for( auto& future : futures ) {
future.wait();
}
为了能够轻松地重复使用,我想出了以下部分代码:
To be able to easily reuse this I came up with the 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;
现在我必须解决 Args
问题,因为在 async_all
, Args
不能被推断。我目前唯一能想到的是另一个函子,它将集合中的一个元素转换为 Args
。
有更好的解决方案吗?
Now I have to solve the Args
problem, since in async_all
, Args
cannot be deduced anymore. The only thing I currently can think of is another functor, which converts an element in collection to Args
.
Is there any more elegant solution to this?
推荐答案
传递给 async_all
的集合具有我们唯一确定函数参数类型所需的所有信息;唯一的问题是如何提取这些信息。使用函数签名中的 auto
关键字,我们可以在函数参数后面写入返回类型。这不仅产生一个更清晰的签名,而且让我们在推导返回类型时使用参数值本身和 decltype
。例如:
You're almost there. The collection passed to async_all
has all the information we need to uniquely determine the function argument type; the only question is how to extract this information. Using the auto
keyword in the function signature, we can write the return type after the function arguments. This not only produces a cleaner signature, but also lets us use the argument values themselves together with decltype
in deducing return types. For instance:
template<typename F, typename CT>
auto reduce(F f, CT coll) -> decltype(f(*begin(coll), *begin(coll));
是用于确定提供的函数的参数类型的其他方法(使用模板的函数签名推导)。但是,对于涉及重载函数和/或模板函数对象的情况,这些方法可能会失败。
Of course, there are other ways to determine argument types for provided functions (using function signature deduction with templates). However, these approaches can fail for cases involving overloaded functions and/or templated function objects.
下面的代码编译并正确运行(打印x = 110次)在gcc 4.8(早期版本应该工作正常)注意我们甚至不必显式提及 std: :future
:我们可以直接在 std :: async
语句中使用decltype来推断它的类型。
The following code compiles and runs properly (prints "x=1" 10 times) under gcc 4.8 (earlier versions should work just fine). Notice how we don't even have to explicitly mention std::future
: we can use decltype directly on the std::async
statement to 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());
for (auto& element : col) {
futures.push_back(std::async(f, element));
}
return futures;
}
int main()
{
using namespace std;
for (auto& f : async_all([](int x) { cout << "x = " << x << endl; },
vector<int>(10, 1)))
f.get();
}
( async_all
这里只计算一次,因为规范保证范围表达式在基于范围的循环)
(async_all
is evaluated just once here, as the spec guarantees for range expressions in range-based for loops)
这篇关于std :: async变体,它处理集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!