将返回 std::future 的函数调整为<T> std::future<U>
Adapting a function that returns std::future<T> to std::future<U>
假设我有一个异步函数映射原始映射,它将std::vector
作为输入,并将std::future
返回到我选择的Container
作为输出:
template<class Container, class T, class Function>
std::future<Container> async_map(const std::vector<T>& in, Function f)
{
return std::async([=]
{
Container result(in.size());
for(size_t i = 0; i < in.size(); ++i)
{
result[i] = f(in[i]);
}
return result;
});
}
我想通过调整async_map
来构建类似的async_for_each
功能:
template<class T, class Function>
std::future<void> async_for_each(const std::vector<T>& in, Function f);
问题是async_for_each
返回std::future<void>
,而async_map
返回std::future<Container>
,而void
不是Container
。
我可以通过构造满足Container
要求但忽略其分配的类型来获得我想要的东西(在我的初步尝试中empty_container
),但是这种类型的std::future
仍然不是std::future<void>
。
我对我的解决方案有以下约束:
- 必须只有一个
async_map
的实现,具有给定功能签名(即无async_map<void>
专业化) - 必须只创建一个
std::future
(即无.then()
-风格延续)
我希望有一种有效的方法可以在相关类型的std::future
s之间进行转换(或将std::future<T>
施加到std::future<void>
),但是这个问题的答案表明这是不可能的。
随机想法:
-
async_for_each
可以以一种巧妙的方式包装其功能来解决此问题? -
Container
使用的类型可以像async_for_each
中的void
一样起作用,但可以像async_map
中的Container
一样行动?
我的最初尝试在下面。有可能在这些约束下构建我想要的东西吗?
#include <future>
#include <vector>
#include <iostream>
template<class Container, class T, class Function>
std::future<Container> async_map(const std::vector<T>& in, Function f)
{
return std::async([=]
{
Container result(in.size());
for(size_t i = 0; i < in.size(); ++i)
{
result[i] = f(in[i]);
}
return result;
});
}
struct empty_container
{
empty_container(size_t) {}
struct empty
{
template<class T>
empty operator=(const T&) const { return empty(); }
};
empty operator[](size_t) { return empty(); }
};
template<class Function>
struct invoke_and_ignore_result
{
Function f;
template<class T>
empty_container::empty operator()(T&& x) const
{
f(std::forward<T>(x));
return empty_container::empty();
}
};
template<class T, class Function>
//std::future<void> async_for_each(const std::vector<T>& in, Function f)
std::future<empty_container> async_for_each(const std::vector<T>& in, Function f)
{
invoke_and_ignore_result<Function> g{f};
std::future<empty_container> f1 = async_map<empty_container>(in, g);
return f1;
}
int main()
{
std::vector<int> vec(5, 13);
async_for_each(vec, [](int x)
{
std::cout << x << " ";
}).wait();
std::cout << std::endl;
return 0;
}
我认为您正在使用错误的原始。
在这里,我用不同的原始构建一切 - 水槽。
水槽可以通过operator()(T&&)&
消耗数据。然后,它通过operator()()&&
返回一些结果。
这是async_sink
函数:
template<class Container, class Sink>
std::future<std::result_of_t<std::decay_t<Sink>()>>
async_sink(Container&& c, Sink&& sink)
{
return std::async(
[c=std::forward<Container>(c), sink=std::forward<Sink>(sink)]
{
for( auto&& x : std::move(c) ) {
sink( x );
}
return std::move(sink)();
});
}
这是将物品放入容器中的sink
的实现,然后返回:
template<class C>
struct container_sink_t {
C c;
template<class T>
void operator()( T&& t ){
c.emplace_back( std::forward<T>(t) );
}
C operator()()&&{
return std::move(c);
}
};
这是一个接收器,可以采用一个功能和一个水槽并组成它们:
template<class F, class S>
struct compose_sink_t {
F f;
S s;
template<class T>
void operator()(T&& t){
s(
f(std::forward<T>(t))
);
}
std::result_of_t<S()> operator()()&&{
return std::move(s)();
}
};
template<class C, class F>
compose_sink_t<std::decay_t<F>, container_sink_t<C>>
transform_then_container_sink( F&& f ) {
return {std::forward<F>(f)};
}
这是一个接收器,可以采用功能,调用它并返回void
:
template<class F>
struct void_sink_t {
F f;
template<class T>
void operator()(T&& t)
{
f(std::forward<T>(t));
}
void operator()() {}
};
template<class F>
void_sink_t<std::decay_t<F>> void_sink(F&&f){return {std::forward<F>(f)}; }
现在您的地图是:
template<class Container, class T, class Function>
std::future<Container> async_map(const std::vector<T>& in, Function f)
{
return async_sink(
in,
transform_then_container_sink<Container>(std::forward<F>(f))
);
}
和您的for_each是:
template<class T, class Function>
std::future<void> async_for_each(const std::vector<T>& in, Function f)
{
return async_sink(
in,
void_sink(std::forward<F>(f))
);
}
我自由使用C 14个功能,因为它们使代码更好。您可以用副本替换Move-Into-Container,以提高触摸效率,并编写您自己的_t
别名。
上面的代码尚未进行测试或运行,因此其中可能有错误。我不确定存在一个问题 - 在这种情况下,兰伯达能否以return void_func()
返回void? - 但是由于丑陋在一个位置,即使它不起作用也可以解决。
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- ///<评论></评论>在Visual Studio中