#ifndef coro_02_h
#define coro_02_h

#include <coroutine>

// Die Coroutinen-Klasse
template <typename T>
struct MyCoroutine
{
    struct promise_type;
    using handle = std::coroutine_handle<promise_type>;
    // promise_type Klasse
    struct promise_type
    {
        // Letzter aus der Coroutine zurueckgegebener Wert
        T saved_value;
        // Aufruf unmittelbar nach Start der Coroutine
        auto initial_suspend()
        {
            return std::suspend_always{};
        }
        // Aufruf nach Beenden der Coroutine
        auto final_suspend() noexcept
        {
            return std::suspend_always{};
        }
        // Aufruf beim Ausloesen einer nicht behandelten
        // Ausnahme
        void unhandled_exception()
        {
            std::terminate();
        }
        // Liefert das Coroutinen-Objekt zurueck
        auto get_return_object()
        {
            return MyCoroutine{ handle::from_promise(*this) };
        }
        // Aufruf durch co_return
        void return_value(T value)
        {
            saved_value = value;
        }
    };
    // Setzt die Ausfuehrung der Coroutine fort (coro.resume()),
    // wenn das Coroutinen-Handle gueltig ist (ungleich 0)
    bool resume()
    {
        return coro ? (coro.resume(), !coro.done()) : false;
    }
    // const-Referenz auf Datum zurueckgeben
    const T& GetValue() const
    {
        return coro.promise().saved_value;
    }
private:
    // Coroutinen-Handle
    handle coro;
    // ctor, speichert das uebergebene Coroutinen-Handle ab
    MyCoroutine(handle h) : coro(h)
    {
    }
};
#endif
