Skip to content

Instantly share code, notes, and snippets.

@GorNishanov
Last active February 8, 2019 04:54
Show Gist options
  • Save GorNishanov/03d6375e2785e1a29018c5fde93437a3 to your computer and use it in GitHub Desktop.
Save GorNishanov/03d6375e2785e1a29018c5fde93437a3 to your computer and use it in GitHub Desktop.
#ifndef EXPERIMENTAL_SIMPLE_GENERATOR
# define EXPERIMENTAL_SIMPLE_GENERATOR
#include <experimental/coroutine>
namespace std::experimental {
template <typename T> struct generator {
struct promise_type {
T current_value;
suspend_always yield_value(T value) {
this->current_value = value;
return {};
}
suspend_always initial_suspend() { return {}; }
suspend_always final_suspend() { return {}; }
generator get_return_object() { return generator{this}; };
void unhandled_exception() { std::terminate(); }
void return_void() {}
};
struct iterator {
coroutine_handle<promise_type> _Coro;
bool _Done;
iterator(coroutine_handle<promise_type> Coro, bool Done)
: _Coro(Coro), _Done(Done) {}
iterator &operator++() {
_Coro.resume();
_Done = _Coro.done();
return *this;
}
bool operator==(iterator const &_Right) const {
return _Done == _Right._Done;
}
bool operator!=(iterator const &_Right) const { return !(*this == _Right); }
T const &operator*() const { return _Coro.promise().current_value; }
T const *operator->() const { return &(operator*()); }
};
iterator begin() {
p.resume();
return {p, p.done()};
}
iterator end() { return {p, true}; }
generator(generator const&) = delete;
generator(generator &&rhs) : p(rhs.p) { rhs.p = nullptr; }
~generator() {
if (p)
p.destroy();
}
private:
explicit generator(promise_type *p)
: p(coroutine_handle<promise_type>::from_promise(*p)) {}
coroutine_handle<promise_type> p;
};
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment