#ifndef FORKABLEFUTURE_H #define FORKABLEFUTURE_H #include #include #include #include template class ForkableFuture { public: ForkableFuture(const QFuture& future, QObject* parent = nullptr) : watcher(new QFutureWatcher(parent)) { watcher->connect(watcher, &QFutureWatcher::started, [this]() { for (auto& promise : promises) { promise->start(); } }); watcher->connect(watcher, &QFutureWatcher::finished, [this]() { for (auto& promise : promises) { promise->addResult(watcher->result()); promise->finish(); } }); watcher->setFuture(future); } // Delete the copy constructor ForkableFuture(const ForkableFuture&) = delete; // Enable the move constructor ForkableFuture(ForkableFuture&& other) noexcept : watcher(std::exchange(other.watcher, nullptr)), promises(std::move(other.promises)) {} ~ForkableFuture() { for (auto promise : promises) { delete promise; } delete watcher; } // Delete the copy assignment operator ForkableFuture& operator=(const ForkableFuture&) = delete; // Enable the move assignment operator ForkableFuture& operator=(ForkableFuture&& other) noexcept { if (this != &other) { watcher = std::exchange(other.watcher, nullptr); promises = std::move(other.promises); } return *this; } template auto then(F&& continuation) { auto promise = new QPromise(); promises.append(promise); auto future = promise->future().then(continuation); if (watcher->isRunning()) { promise->start(); } else if (watcher->isFinished()) { promise->addResult(watcher->result()); promise->finish(); } return future; } private: QFutureWatcher* watcher; QList*> promises; }; #endif // FORKABLEFUTURE_H