【问题标题】:async doesn't invoke move constructor in Visual Studio 2015async 不会在 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 实现似乎支持仅移动参数就好了(我猜你可以将其用作解决方法)。

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


【解决方案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,不是它的忠实粉丝 - 由于一些设计缺陷。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-19
  • 2011-05-22
  • 1970-01-01
  • 2015-02-21
  • 2012-05-05
  • 2012-10-10
  • 1970-01-01
相关资源
最近更新 更多