std::async decaying(losing) rvalue reference in Visual Studio 2012 Update 2. Any workarounds?

陌路散爱 提交于 2019-12-23 08:40:02

问题


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.


回答1:


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!



来源:https://stackoverflow.com/questions/16140293/stdasync-decayinglosing-rvalue-reference-in-visual-studio-2012-update-2-any

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!