suspend-next.cpp

#include <coroutine>
#include <iostream>

class Coro {
public:
    struct promise_type
    {
        Coro get_return_object() { return Coro(this); }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always yield_value(std::string v) // <--- called by co_yield  
        { 
            last_value = v;                            // <--- save yielded value
            return {};
        }
        std::suspend_always final_suspend() noexcept(true) { return {}; }
        void return_void() {}        
        void unhandled_exception() {}
        std::string last_value;                        // <--- last value co_yield'ed
    };

public:
    Coro(promise_type* p) : _promise(p) {}
    struct StopIteration {};                           // <--- Python-style sentinel exception
    std::string next()                                 // <--- produce next element, or throw StopIteration
    {
        auto coro = std::coroutine_handle<promise_type>::from_promise(*_promise);
        coro.resume();
        if (coro.done())
            throw StopIteration();
        return _promise->last_value;
    }

private:
    promise_type* _promise;
};

Coro hello()
{
    std::cout << "Saying Hello" << std::endl;
    co_yield "Hello";
    std::cout << "Not Saying Bye" << std::endl;
    co_return;
}

int main()
{
    auto hello_instance = hello();

    while (true) {
        try {
            std::cout << hello_instance.next() << std::endl;
        }
        catch (const Coro::StopIteration&) {
            break;
        }
    }

    return 0;
}