std :: async在Visual Studio 2012 Update 2中衰减(丢失)右值引用。任何解决方法? [英] std::async decaying(losing) rvalue reference in Visual Studio 2012 Update 2. Any workarounds?

查看:304
本文介绍了std :: async在Visual Studio 2012 Update 2中衰减(丢失)右值引用。任何解决方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码:

  #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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆