c++ - 适用于集合的 std::async 变体

标签 c++ concurrency c++11 future

使用 std::async 我想知道是否有可能有一个辅助函数,它从一个集合中创建 std::future(每个 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_all 中,Args 不能再推导了。我目前唯一能想到的是另一个仿函数,它将集合中的元素转换为Args。 有没有更优雅的解决方案?

最佳答案

你快到了。传递给 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:我们可以直接在 std::async 语句上使用 decltype 来推断它的类型。

#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 在这里只计算一次,因为规范保证了基于范围的 for 循环中的范围表达式)

关于c++ - 适用于集合的 std::async 变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10902230/

相关文章:

java - 线程作为 Java 对象

c++ - 同时具有模板和非模板构造函数的类

c++ - C++ 中的 funcall : declaring functions that take functions as parameters

c++ - 减少通过 UDP 套接字发送的数据

java - 如何在HashMap中实现入门级锁定?

java - 阻塞队列与信号量

c++ - 将动态二维数组在 C++ 和 Fortran 之间传递

c++ - 我的构造函数方法不接受参数 (directX/windows)

c++ - 为什么人们不像控制台应用程序那样将 C++ 用于 GUI?

c++ - vs2005中如何调试别人调用的exe