将虚拟拷贝构造函数添加到std :: packaged_task

时间:2016-10-12 10:17:34

标签: c++ c++11 packaged-task

我试图绕过std :: packaged_task缺少复制构造函数,以便我可以将它传递给std :: function(只会被移动)。

我从std :: packaged_task继承并添加了一个虚拟拷贝构造函数,如果我从未复制它移入的std ::函数,我认为不应该调用它。

#include <iostream>
#include <future>
#include <functional>
#include <thread>

template <typename T>
class MyPackagedTask : public std::packaged_task<T()> {
  public:
    template <typename F>
    explicit MyPackagedTask(F&& f)
      : std::packaged_task<T()>(std::forward<F>(f)) {}

    MyPackagedTask(MyPackagedTask&& other)
      : std::packaged_task<T()>(std::move(other)) {}

    MyPackagedTask(const MyPackagedTask& other) {
      // Adding this borks the compile
    }
};

int main()
{
    MyPackagedTask<int> task([]() {return 0;});
    auto future = task.get_future();
    std::thread t(std::move(task));
    t.join();

    std::cout << future.get() << std::endl;
}

使用gcc 6.2.1进行编译我收到以下错误消息(只是结束部分,如果你想要整件事,请告诉我......):

/usr/include/c++/6.2.1/future:1325:6: error: invalid use of void expression
      (*_M_result)->_M_set((*_M_fn)());

错误消息对我来说是无法解析的,所以我想知道我是做错了什么还是编译器失败了。

1 个答案:

答案 0 :(得分:1)

移动构造函数定义不正确,它将std::packaged_task<T()>&&转发为MyPackagedTask&&并调用std::packaged_task<T()>的错误构造函数。这是您观察到编译器错误的原因。

正确的一个:

MyPackagedTask(MyPackagedTask&& other)
  : std::packaged_task<T()>(static_cast<std::packaged_task<T()>&&>(other))
{}

在那里,static_cast<std::packaged_task<T()>&&>(other)同时完成基类的上传和std::move