向std::packaged_task添加虚拟复制构造函数

Adding dummy copy constructor to std::packaged_task

本文关键字:虚拟 复制 添加 构造函数 std packaged task      更新时间:2023-10-16

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

我继承了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)());

错误信息对我来说是不可解析的,所以我想知道我是否做错了什么,或者如果编译器失败。

move构造函数定义不正确,将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