在Visual Studio 2013中为rvalue引用初始化捕获
init-capture for rvalue reference in Visual Studio 2013
我想在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()
的函数对象),而当前不允许使用constexpr
lambdas(解决办法:文本类型的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
- C++-模板嵌套类的引用初始化无效
- 在引用初始化中使用已删除的复制构造函数进行复制初始化
- 模板流运算符重载错误:引用初始化无效,与basic_istream和basic_ifstream之间的差异有关
- 具有字符串文本构造函数的类不适用于 const 引用初始化
- 类型为"短整型 (&)"的引用初始化无效
- 引用初始化和常量表达式
- 在Visual Studio 2013中为rvalue引用初始化捕获
- 从大括号括起来的初始值设定项列表进行的Lvalue引用初始化无法编译
- Visual C++ 2015 中右值的非常量引用初始化无效
- 是否可以使用对派生类实例的基类引用初始化派生类引用
- 类型'int&'的引用初始化无效,传递参数 1 时出错
- 引用初始化表单
- 从类型为"int*"的临时引用初始化类型为"int&"的非常量引用无效
- 简单的C++日志记录类-ostream引用初始化
- 错误:类型为"cv::Mat&"的非常量引用初始化无效
- 为什么我收到类型为"const vec&"的引用初始化无效
- 从类型为"char*"的临时引用初始化类型为"char*&"的非常量引用
- 为什么这会发送一个关于引用初始化无效的错误
- 为什么此处不对引用初始化执行复制初始化?
- std::vector不会为多个向量条目创建cv::Mat的新引用——初始化矩阵时,数据会被覆盖