CodeNebula
C++20coreadvanced

co_return (C++20 Addition)

C++20 · The Big Four · Compiler flag: -std=c++20

Explanation

Returns a value from a coroutine, completing it.

Real-World Scenario

Return the result of an async computation in a server.

Quick Snippet

snippet.cpp
#include <coroutine> auto task() { co_return 42; }

Full Example

co_return.cpp
// CodeNebula - C++20 Example: co_return with Task/Future Pattern
// Compile: g++ -std=c++20 -Wall -Wextra -o example co_return.cpp

// co_return completes a coroutine and optionally provides a final value.
// It is the coroutine equivalent of 'return'. The value goes through
// the promise_type's return_value() or return_void() method.

#include <iostream>
#include <coroutine>
#include <string>

// --- Task<T>: a coroutine that produces a single result via co_return ---
template <typename T>
struct Task {
    struct promise_type {
        T result;
        std::exception_ptr exception = nullptr;

        Task get_return_object() {
            return Task{std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_value(T value) { result = std::move(value); }
        void unhandled_exception() { exception = std::current_exception(); }
    };

    std::coroutine_handle<promise_type> handle;

    explicit Task(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~Task() { if (handle) handle.destroy(); }
    Task(const Task&) = delete;
    Task(Task&& o) noexcept : handle(o.handle) { o.handle = nullptr; }
    Task& operator=(const Task&) = delete;

    T result() const {
        if (handle.promise().exception)
            std::rethrow_exception(handle.promise().exception);
        return handle.promise().result;
    }
};

// --- VoidTask: a coroutine that completes without a value ---
struct VoidTask {
    struct promise_type {
        bool completed = false;
        VoidTask get_return_object() {
            return VoidTask{std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() { completed = true; }
        void unhandled_exception() { std::terminate(); }
    };

    std::coroutine_handle<promise_type> handle;
    explicit VoidTask(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~VoidTask() { if (handle) handle.destroy(); }
    VoidTask(const VoidTask&) = delete;
    VoidTask(VoidTask&& o) noexcept : handle(o.handle) { o.handle = nullptr; }
    VoidTask& operator=(const VoidTask&) = delete;

    bool completed() const { return handle.promise().completed; }
};

// Coroutine returning an int via co_return
Task<int> compute_sum(int a, int b) {
    std::cout << "  Computing " << a << " + " << b << "...\n";
    co_return a + b;
}

// Coroutine returning a string via co_return
Task<std::string> greet(const std::string& name) {
    std::cout << "  Building greeting for " << name << "...\n";
    co_return "Hello, " + name + "!";
}

// Coroutine with conditional co_return
Task<int> safe_divide(int a, int b) {
    if (b == 0) {
        std::cout << "  Division by zero — returning -1\n";
        co_return -1;  // early co_return
    }
    std::cout << "  Computing " << a << " / " << b << "...\n";
    co_return a / b;
}

// Void coroutine using co_return (no value)
VoidTask log_message(const std::string& msg) {
    std::cout << "  [LOG] " << msg << "\n";
    co_return;  // completes without a value
}

int main() {
    std::cout << "=== co_return with Task Pattern ===\n\n";

    auto sum = compute_sum(10, 20);
    std::cout << "Result: " << sum.result() << "\n\n";

    auto greeting = greet("C++20");
    std::cout << "Result: " << greeting.result() << "\n\n";

    auto div1 = safe_divide(100, 7);
    std::cout << "Result: " << div1.result() << "\n\n";

    auto div2 = safe_divide(42, 0);
    std::cout << "Result: " << div2.result() << "\n\n";

    auto log = log_message("Task completed successfully");
    std::cout << "Void task completed: " << std::boolalpha << log.completed() << "\n";

    return 0;
}

// Expected output:
// === co_return with Task Pattern ===
//
//   Computing 10 + 20...
// Result: 30
//
//   Building greeting for C++20...
// Result: Hello, C++20!
//
//   Computing 100 / 7...
// Result: 14
//
//   Division by zero — returning -1
// Result: -1
//
//   [LOG] Task completed successfully
// Void task completed: true
Run command
g++ -std=c++20 -Wall -Wextra -o example co_return.cpp