std :: async在Visual Studio 2012 Update 2中衰减(丢失)右值引用。任何解决方法? [英] std::async decaying(losing) rvalue reference in Visual Studio 2012 Update 2. Any workarounds?
问题描述
请考虑以下代码:
#include< memory>
#include< future>
using namespace std;
template< typename T,typename Work>
void Test2(future< T> f,Work w)
{
async([](future< T& f,Work w)
{}, move(f),move(w));
}
int main()
{
future< int> x = std :: async([]() - > int {
std :: this_thread :: sleep_for(std :: chrono :: microseconds(200));
return 10;
});
Test2(std :: move(x),[](int x){});
return 0;
}
上述操作失败,出现以下编译错误:
错误1错误C2664:'void
Test2 :::: operator
()(std :: future< _Ty>&& ;,Work)const':不能将参数1从
'std :: future< _Ty>'转换为'std :: future< _Ty>&'c:\program文件
x86)\microsoft visual studio
11.0 \vc\include\xrefwrap 98 1 ConsoleApplication6
GCC 4.7。 2编译就好了
http://ideone.com/KhMiV6
在我继续前面并在Microsoft Connect上报告:
1)这是VC11的一个错误还是这是标准的行为? / p>
2)有没有人知道这个问题的解决方法?
编辑: =https://connect.microsoft.com/VisualStudio/feedback/details/785260/std-async-decaying-losing-rvalue-reference-in-visual-studio-2012-update-2 =nofollow> Microsoft在此处。为了更快的分辨率,鼓励你upvote它。
Hm,它似乎是VC11中的一个错误。显然, async
的实现并不真正转发参数,而是复制它们。
从头顶我将创建一个小的包装器的右值,移动构造元素时,包装器被复制:
template< typename T& ;
struct rvref_wrapper {
rvref_wrapper(T& value):value_(std :: move(value)){}
rvref_wrapper(rvref_wrapper const& other):value_(other.get )){}
T&& get()const {return std :: move(value_);} }
mutable T value_;
};
template< typename T>
auto rvref(T&& x) - > rvref_wrapper< typename decay< T> :: type> {
return std :: move(x);
}
然后你必须修改你的测试场景, Test2
采用包装而不是未来
本身:
template< typename T,typename Work>
void Test2(future< T> f,Work w)
{
async([(rvref_wrapper< future< T> fr,Work w){
//获取将来< T&&&&&&&&&&>这里
future< T f(fr.get());
//例如使用未来值
w(f.get ;
},rvref(f),move(w));
}
int main()
{
future< int> x = std :: async([]() - > int {
std :: this_thread :: sleep_for(std :: chrono :: microseconds(200));
return 10;
});
Test2(std :: move(x),[](int x){});
return 0;
}
看起来有点丑,但至少它编译。希望能帮助你!
Consider the below code:
#include <memory>
#include <future>
using namespace std;
template <typename T, typename Work>
void Test2(future<T> f, Work w)
{
async([](future<T> && f, Work w)
{}, move(f), move(w));
}
int main()
{
future<int> x = std::async([]()->int{
std::this_thread::sleep_for(std::chrono::microseconds(200));
return 10;
});
Test2(std::move(x), [](int x){});
return 0;
}
The above, fails with the following compiler error:
Error 1 error C2664: 'void Test2::::operator ()(std::future<_Ty> &&,Work) const' : cannot convert parameter 1 from 'std::future<_Ty>' to 'std::future<_Ty> &&' c:\program files (x86)\microsoft visual studio 11.0\vc\include\xrefwrap 98 1 ConsoleApplication6
GCC 4.7.2 compiles just fine http://ideone.com/KhMiV6
Before I go ahead and report it on Microsoft Connect:
1) Is this a bug on VC11's part or is this actually standard behavior?
2) Does anyone know of a workaround for this?
EDIT: I have reported it on Microsoft Connect here. For faster resolution, you are encouraged to upvote it.
Hm, it seems to be a bug in VC11. Apparently the implementation of async
doesn't really forward the arguments but copies them.
From the top of my head I would create a small wrapper for the rvalue that move-constructs the element when the wrapper is copied:
template <typename T>
struct rvref_wrapper {
rvref_wrapper(T&& value) : value_(std::move(value)) {}
rvref_wrapper(rvref_wrapper const& other) : value_ (other.get()) {}
T&& get() const { return std::move(value_); }
mutable T value_;
};
template <typename T>
auto rvref(T&& x) -> rvref_wrapper<typename decay<T>::type> {
return std::move(x);
}
Then you'd have to modify your test scenario, so that the lambda in Test2
takes the wrapper instead of the future
itself:
template <typename T, typename Work>
void Test2(future<T> f, Work w)
{
async([](rvref_wrapper<future<T>> fr, Work w) {
// acquire future<T>&& here
future<T> f(fr.get());
// e.g. call work with future value
w(f.get());
}, rvref(f), move(w));
}
int main()
{
future<int> x = std::async([]()->int{
std::this_thread::sleep_for(std::chrono::microseconds(200));
return 10;
});
Test2(std::move(x), [](int x){});
return 0;
}
Looks a little bit ugly, but at least it compiles. Hope that helps you!
这篇关于std :: async在Visual Studio 2012 Update 2中衰减(丢失)右值引用。任何解决方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!