std :: async变体,它处理集合 [英] std::async variant which works over a collection

查看:100
本文介绍了std :: async变体,它处理集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 std :: async 我想知道是否可能有一个帮助函数,它创建 std :: future

Using std::async I was wondering whether it is possible to have a helper function, which creates std::futures 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆