async doesn't invoke move constructor in Visual Studio 2015

时间:2015-10-06 08:53:49

标签: c++ visual-studio c++11 visual-c++

I have a problem compiling the code containing the following on Visual Studio 2015 Community

auto f = async(launch::async,                  
          &WorkerThread<Hash>::run,                 
          WorkerThread<Hash>(mInputFile, mOutputFile),
          i, numthreads, mBlockSize);                   
futures.push_back(std::move(f));    

Well, similar questions have been asked here dozens of times, but usually the problem was the absent std::move somewhere.

Template class WorkerThread<Hash> is not copyable (has deleted copy constructor and copy assignment operator), but is movable. The above code produces C2280: "WorkerThread<Hash>::WorkerThread(const WorkerThread<Hash> &)": attempted to reference deleted function (this is my translation).

It seems like it is not generating move constructor by default, which would be fine in my case. When I explicitly set them to default, I get the same error, but now it refers to std::_Binder<std::_Unforced,_Ty,WorkerThread<Hash>,unsigned int,unsigned int,__int64>::_Binder(const std::_Binder<std::_Unforced,_Ty,WorkerThread<Hash>,unsigned int,unsigned int,__int64> &).

Any ideas are very welcome.

Update: MCVE

If you have the mentioned compiler available, please, try to compile this and report the result. I think it might me an installation problem.

#include<future>
#include<memory>


class Foo {
public:
    Foo() :mData(new int[100]) {}
    void run() {}
private:
    std::unique_ptr<int[]> mData;
};


int main()
{
    auto f = std::async(std::launch::async, &Foo::run, Foo());
    f.get();
}

1 个答案:

答案 0 :(得分:4)

修改:该错误已在MSVC 2015 Update 2中修复。

这是一个MSVC bug(帽子提示@bogdan,用于查找报告)。它的async(和packaged_task似乎)实现将仿函数存储到std::function中,它不支持仅移动类型 - 因此不能用于符合标准的实现

一个简单的解决方法是改为使用shared_ptr

auto f = async(launch::async,                  
          &WorkerThread<Hash>::run,                 
          std::make_shared<WorkerThread<Hash>>(mInputFile, mOutputFile),
          i, numthreads, mBlockSize);                   
futures.push_back(std::move(f));

也可以考虑Lambdas(沿[=]{WorkerThread<Hash>(mInputFile, mOutputFile).run(i, numthreads, mBlockSize); }行),但这会导致行为发生变化:WorkerThread<Hash>不再在调用async的线程中构建,但是在线程async中生成。