在Visual Studio 2013中为rvalue引用初始化捕获

init-capture for rvalue reference in Visual Studio 2013

本文关键字:引用 初始化 rvalue 中为 Visual Studio 2013      更新时间:2023-10-16

我想在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捕获,一个C++14特性。如何使用VC++2013运行此代码?

(我想使用lambda,所以请不要告诉我"只使用函数对象结构!")

(我尝试过在lambda中移动捕获,但它不起作用。)

(如果你不仅回答我的问题,而且改进我的代码,我将不胜感激)

很遗憾,Visual Studio 2013中还没有此功能。它于2014年6月发布,带有Visual Studio"14"CTP(社区技术预览版,具有alpha质量,不适合生产代码)。报价:

以下是Visual C++的改进:

广义lambda捕获:您可以为表达式转换为lambda的捕获子句中的变量。这允许按值捕获仅移动类型的实例

正如评论中所指出的:作为Visual Studio 2013的解决方案,您可以使用通过构造函数初始化的局部变量来创建自己的函数对象。是的,这很糟糕,但在兰达斯发明之前,这一直是标准的技巧。多态lambdas也是如此,直到它们得到支持(解决方法:具有模板化operator()的函数对象),而当前不允许使用constexprlambdas(解决办法:文本类型的constexpr函数对象)。

还有两个其他选项,使用std::bind并编写一个移动副本包装器。

所以你可以做

return std::async(std::bind(
[func](std::future<void> & fu) mutable { fu.get(); return func(); },
std::move(fu)
);

关于复制包装器的移动,我可以向您介绍如何捕获std::unique_ptr"通过移动";对于std::for_each 中的lambda