async 不会在 Visual Studio 2015 中调用移动构造函数

Posted

技术标签:

【中文标题】async 不会在 Visual Studio 2015 中调用移动构造函数【英文标题】:async doesn't invoke move constructor in Visual Studio 2015 【发布时间】:2015-10-06 08:53:49 【问题描述】:

我在 Visual Studio 2015 社区编译包含以下内容的代码时遇到问题

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

好吧,类似的问题已经在这里问了几十次了,但通常问题出在某处缺少std::move

模板类WorkerThread&lt;Hash&gt; 不可复制(已删除复制构造函数和复制赋值运算符),但可移动。上面的代码产生C2280: "WorkerThread&lt;Hash&gt;::WorkerThread(const WorkerThread&lt;Hash&gt; &amp;)": attempted to reference deleted function(这是我的翻译)。

似乎默认情况下它不会生成移动构造函数,在我的情况下这很好。当我将它们显式设置为default 时,我得到了同样的错误,但现在它指的是std::_Binder&lt;std::_Unforced,_Ty,WorkerThread&lt;Hash&gt;,unsigned int,unsigned int,__int64&gt;::_Binder(const std::_Binder&lt;std::_Unforced,_Ty,WorkerThread&lt;Hash&gt;,unsigned int,unsigned int,__int64&gt; &amp;)

非常欢迎任何想法。

更新:MCVE

如果您有上述编译器可用,请尝试编译并报告结果。我认为这可能是我的安装问题。

#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();

【问题讨论】:

您没有发布所有错误,但我猜您可能应该使用 futures.emplace_back(std::move(f));而不是 push_back? @Jonathan,不,同样的结果 @T.C.,完成。这段代码不适合我。 MSVC 错误。它将它打包成一个std::function,这是不应该的。 在 MS Connect 上有几个与此相关的错误报告。我能找到的最新消息是:std::async (still?) does not accept move only types。支持它并将其标记为可重现不会有什么坏处。这很烦人,因为他们的 std::thread 实现似乎支持仅移动参数就好了(我猜你可以将其用作解决方法)。 【参考方案1】:

编辑:该错误已在 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));

也可以考虑 Lambda(沿着 [=]WorkerThread&lt;Hash&gt;(mInputFile, mOutputFile).run(i, numthreads, mBlockSize); 的行),但这会导致行为发生变化:WorkerThread&lt;Hash&gt; 不再在调用 async 的线程中构造,而是在线程 async 中构造产卵。

【讨论】:

看看你能不能找到 Herb Sutter 关于std::async 主题的视频。 IIRC,不是它的忠实粉丝 - 由于一些设计缺陷。

以上是关于async 不会在 Visual Studio 2015 中调用移动构造函数的主要内容,如果未能解决你的问题,请参考以下文章

在 Visual Studio 中,与 std::async 一起使用时未调用“thread_local”变量的析构函数,这是一个错误吗?

异步/等待异常和 Visual Studio 2013 调试输出行为

Visual Studio 2012 项目不会在 2010 年打开

Visual Studio Online 上的远程分支不会出现在 Visual Studio 2015 Team Explorer 上

Visual Studio 2015发布失败

visual studio 2017许可证过期怎么办