假设我有一个异步函数映射原语,它以 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
之间进行转换(或将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;
}