的std ::异步变体,它的工作原理在集合(std::async variant which wor

2019-09-17 18:30发布

使用std::async我想知道是否有可能有一个辅助函数,它创建std::future从一个集合(一个未来每个集合元素)秒。

我常常有以下情况:

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

为了能够轻松地重复使用这一点,我想出了下面的部分代码:

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_allArgs不能再推断。 目前,我能想到的唯一的事情就是另一个仿函数,它在集合中的元素转换为Args 。 有没有更好的解决方案来呢?

Answer 1:

你快到了。 传递给收集async_all有需要我们唯一确定的函数参数类型的所有信息; 唯一的问题是如何提取这些信息。 使用auto在函数签名关键字,就可以写出函数的参数后返回类型。 这不仅会产生一个更清洁的签名,但也让我们使用参数值与自己一起decltype在推断返回类型。 例如:

template<typename F, typename CT>
auto reduce(F f, CT coll) -> decltype(f(*begin(coll), *begin(coll));

当然,还有其他的方法来确定参数类型提供的功能(使用函数签名抵扣模板)。 然而,这些方法可能会失败涉及重载函数和/或模板函数对象的情况。

下面的代码编译,并在GCC 4.8运行正常(打印出“X = 1”的10倍)(早期版本的应该只是罚款)。 请注意如何,我们甚至没有明确提到std::future :我们可以直接使用decltype上std::async语句来推断它的类型。

#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只是计算一次在这里,作为规范担保范围内的表达范围为基础的循环)



文章来源: std::async variant which works over a collection