#include <cassert>
#include <coroutine>
#include <iostream>

template <typename Ty_>
struct Generator {

    /*
    ** Promise implementation.
    */
    struct promise_type {
        Ty_ m_val;

        Generator get_return_object() {
            return this;
        }

        std::suspend_never initial_suspend() {
            return {};
        }

        std::suspend_always final_suspend() noexcept(true) {
            return {};
        }

        std::suspend_always yield_value(const Ty_& val) {
            m_val = val;
            return {};
        }
        void unhandled_exception() {}
    };

    /*
    ** Iterator implementation.
     */
    struct iterator {

        bool operator!=(const iterator &rhs) {
            return not m_h_ptr->done();
        }

        iterator &operator++() {
            m_h_ptr->resume();
            return *this;
        }

        int operator*() {
            return m_h_ptr->promise().m_val;
        }

        std::coroutine_handle<promise_type> *m_h_ptr;
    };

    iterator begin() {
        return iterator{&m_handle};
    }

    iterator end() {
        return iterator{nullptr};
    }

  /* ----------------------------------------------------------------------------------
   */
    Generator(promise_type *p) : m_handle(std::coroutine_handle<promise_type>::from_promise(*p)) {}

    ~Generator() {
        m_handle.destroy();
    }

    std::coroutine_handle<promise_type> m_handle;
};

Generator<uint32_t> range(uint32_t start, uint32_t end) {
  while (start != end)
    co_yield start++;
}

int main() {
  for (auto &&no : range(5, 24)) { // Isn't this look like Python !
    std::cout << no << std::endl;
  }
  return EXIT_SUCCESS;
}
