Добавление фиктивного конструктора копирования в std::packaged_task

Я пытаюсь обойти отсутствие в 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)());

Сообщение об ошибке было для меня непонятным, поэтому я подумал, что я делаю что-то не так или компилятор выходит из строя.

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,

Другие вопросы по тегам