我想在C ++中使用.net的System.Threading.Tasks.Task.ContinueWith
,所以我写了以下函数..
#include <iostream>
#include <functional>
#include <future>
template <typename Func, typename Ret>
auto continue_with(std::future<Ret> &&fu, Func func)
-> std::future<decltype(func(fu.get()))>
{
return std::async(
[fu = std::move(fu), func]() mutable { return func(fu.get()); }
);
}
template <typename Func>
auto continue_with(std::future<void> &&fu, Func func)
-> std::future<decltype(func())>
{
return std::async(
[fu = std::move(fu), func]() mutable { fu.get(); return func(); }
);
}
int main()
{
std::future<void> fu = std::async([]{ std::cout << "fu" << std::endl; });
std::future<void> fu2 = continue_with(
std::move(fu),
[]{ std::cout << "fu2" << std::endl; }
);
fu2.get();
std::cout << "fu continue complete" << std::endl;
std::future<int> retfu = std::async([]{ std::cout << "retfu" << std::endl; return 3; });
std::future<int> retfu2 = continue_with(
std::move(retfu),
[](int result){ std::cout << "retfu2 " << result << std::endl; return result + 1; }
);
int ret = retfu2.get();
std::cout << "retfu continue complete : " << ret << std::endl;
std::cin.get();
}
此代码适用于带有-std=c++1y
的gcc 4.8.2。 (我不知道为什么,但它也适用于-std=c++11
)
但它在VC ++ 2013上不起作用。我想这是因为init-capture,一个C ++ 14特性。如何使用VC ++ 2013运行此代码?
(我想使用lambda,所以请不要告诉我“只使用函数对象结构!”)
(我试过Move capture in lambda,但它不起作用..)
(如果您不仅回答我的问题而且还要改进我的代码,我将不胜感激)
答案 0 :(得分:1)
不幸的是,此功能在Visual Studio 2013中尚未出现。它于2014年6月发布,带有Visual Studio "14" CTP(社区技术预览,这是alpha质量,尚未准备好生产代码)。引用:
以下是Visual C ++的改进:
广义lambda捕获:您可以指定评估结果 表达式到lambda的capture子句中的变量。这个 允许按值捕获仅移动类型的实例。
正如评论中指出的:作为Visual Studio 2013的解决方法,您可以使用通过构造函数初始化的局部变量创建自己的函数对象。是的,这很糟糕,但它是发明lambdas之前的标准技巧。在支持多态lambda之前(解决方法:带有模板化operator()
的函数对象)并且当前使用当前不允许的constexpr
lambdas(解决方法:constexpr
文字类型的函数对象也是如此)。
答案 1 :(得分:0)
存在2个其他选项,使用std :: bind并在复制包装上写一个移动。
所以你可以做到
return std::async(std::bind(
[func](std::future<void> & fu) mutable { fu.get(); return func(); },
std::move(fu)
);
复制包装上的移动我可以指向How to capture std::unique_ptr "by move" for a lambda in std::for_each