**QFuture ❤️ C++ coroutines**
Ever since C++20 introduced coroutine support, developers have been eager to integrate it with Qt. The QCoro library was one of the first to emerge, providing a convenient way to write asynchronous code using coroutines. However, it didn't utilize the existing `QFuture` and `QPromise` types in Qt, instead introducing its own mechanisms.
As I delved deeper into this topic, I couldn't help but wonder why no one had created a lightweight wrapper that leveraged the native `QFuture` features. The lack of such a solution became particularly frustrating with a recent project at work, where we encountered a tangled mess of `QFuture::then()` continuations.
**The Solution: qawaitablefuture**
After finally sitting down to tackle this problem, I created the `qawaitablefuture` library, which is now available on GitLab. This single-header library provides a much-needed wrapper around `QFuture`, allowing developers to write coroutine-based code using familiar syntax. It's essentially a thin layer of sugar around `QFuture::then()`, with additional effort invested in propagating cancellation and exceptions.
One of the standout features of this library is its ability to propagate cancellation in both directions: if you co-await a canceled `QFuture`, the outer `QFuture` of the coroutine will be canceled as well. Conversely, if you cancel a suspended coroutine-backed `QFuture`, cancellation will be propagated into the currently awaited `QFuture`.
**Flexibility and Customization**
Developers can configure where their coroutines are resumed using `co_await continueOn(...)`. This function supports the same arguments as `QFuture::then()`, allowing for flexible customization. For example:
```cpp co_await continueOn(this, Qt::AutoConnection); ```
This will resume the coroutine on the `this` object with a connection type of `Qt::AutoConnection`.
**Accessing Underlying Promise**
If you need to check the canceled flag or report progress, you can access the underlying `QPromise` using the `promise()` function:
```cpp auto promise = co_await promise(); if (promise.isCanceled()) { // Handle cancellation... } ```
**Upstreaming Efforts**
I'm planning to upstream this library into Qt. While it's too late for Qt 6.11, which is already in feature freeze, I hope it will make it into Qt 6.12. There have been previous proposals for coroutine support on Qt's Gerrit, but none have made it past the proof-of-concept stage.
**Compatibility Notes**
Be aware that there was a nasty bug in GCC's coroutine support (fixed in GCC 13.0.0) that affects all versions before this release. Specifically, you cannot await an expression involving a temporary lambda:
```cpp co_await foo([&] { /* ... */ }); // Will crash and burn at runtime! ```
To work around this issue, rewrite the code as follows:
```cpp auto f = foo([&] { /* ... */ }); co_await f; ```
This should give you a smooth experience with coroutines in Qt.