暂停通过多个嵌套协程

我尝试低估新协程在C ++ 20中的工作方式,但是除了非常琐碎的示例之外,我无法使其正常工作。

My goal is to create deep nested functions that allow that most inner one could break and return control to most outer code and after some condition it give control back to this inner function. This is effective setjmp and longjmp.

我使用在net中找到的一些示例来填充一些代码:

#include <iostream>
#include <coroutine>
#include <optional>

template <typename T>
struct task 
{
    struct task_promise;

    using promise_type = task_promise;
    using handle_type = std::coroutine_handle<promise_type>;

    mutable handle_type m_handle;

    task(handle_type handle)
        : m_handle(handle) 
    {

    }

    task(task&& other) noexcept
        : m_handle(other.m_handle)
    {
        other.m_handle = nullptr;
    }

    bool await_ready()
    {
        return m_handle.done();
    }

    bool await_suspend(std::coroutine_handle<> handle)
    {
        if (!m_handle.done()) {
            m_handle.resume();
        }
        return !m_handle.done();
    }

    auto await_resume()
    {
        return result();
    }

    T result() const
    {     
        if (!m_handle.done())
            m_handle.resume();

        return *m_handle.promise().m_value;
    }

    //manualy wait for finish
    bool one_step()
    {
        if (!m_handle.done())
            m_handle.resume();
        return !m_handle.done();
    }

    ~task()
    {
        if (m_handle)
            m_handle.destroy();
    }

    struct task_promise 
    {
        std::optional<T>    m_value {};

        auto value()
        {
            return m_value;
        }

        auto initial_suspend()
        {
            return std::suspend_always{};
        }

        auto final_suspend()
        {
            return std::suspend_always{};
        }

        auto return_value(T t)
        {
            m_value = t;
            return std::suspend_always{};
        }

        task<T> get_return_object()
        {
            return {handle_type::from_promise(*this)};
        }

        void unhandled_exception()
        {
            std::terminate();
        }

        void rethrow_if_unhandled_exception()
        {

        }
    };

};

static task<int> suspend_one()
{
    std::cout<< "suspend_one in\n";
    co_await std::suspend_always();
    std::cout<< "suspend_one return\n";
    co_return 1;
}
static task<int> suspend_two()
{
    std::cout<< "suspend_two -> suspend_one #1\n";
    auto a = co_await suspend_one();
    std::cout<< "suspend_two -> suspend_one #2\n";
    auto b = co_await suspend_one();
    std::cout<< "suspend_two return\n";
    co_return a + b;
}

static task<int> suspend_five()
{
    std::cout<< "suspend_five -> suspend_two #1\n";
    auto a = co_await suspend_two();
    std::cout<< "suspend_five -> suspend_one #2\n";
    auto b = co_await suspend_one();
    std::cout<< "suspend_five -> suspend_two #3\n";
    auto c = co_await suspend_two();
    std::cout<< "suspend_five return\n";
    co_return a + b + c;
}

static task<int> run()
{
    std::cout<< "run -> suspend_two #1\n";
    auto a = co_await suspend_two();
    std::cout<< "run -> suspend_one #2\n";
    auto b = co_await suspend_one();
    std::cout<< "run -> suspend_five #3\n";
    auto c = co_await suspend_five();
    std::cout<< "run -> suspend_one #4\n";
    auto d = co_await suspend_one();
    std::cout<< "run -> suspend_two #5\n";
    auto e = co_await suspend_two();
    std::cout<< "run return\n";
    co_return a + b + c + d + e;
}

int main()
{
    std::cout<< "main in\n";
    auto r = run();
    std::cout<< "main -> while\n";
    while (r.one_step()){  std::cout<< "<<<< while loop\n"; }

    std::cout<< "main return\n";
    return r.result();
}

https://gcc.godbolt.org/z/JULJCi

Function run work as expected but I have problem with e.g. suspend_five where it never reach line

std::cout<< "suspend_five -> suspend_two #3\n";

Probably my version of task is completely broken but I have no idea where find this error or how it should look. Or simply thing I want achieve is not supported by C++20? co_yeld could be candidate for work around because it look more possible to nest them manually (for (auto z : f()) co_yeld z;) but goal of this question is to understand internal mechanic of C++20 functionality that solving some existing problem.