Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 52 additions & 72 deletions include/ds/generator.hh
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,21 @@
#define DS_GENERATOR_HH

#include <coroutine>
#include <exception>
#include <utility>

namespace ds {
template<typename T>
class _generator_promise;

template<typename T>
class _generator {
using promise_type = _generator_promise<T>;
struct _generator {
struct promise_type;
struct iterator_type;
using handle_type = std::coroutine_handle<promise_type>;
handle_type handle_;

Comment on lines +8 to 13
public:
struct iterator {
handle_type h_;

T& operator*() const noexcept {
return h_.promise().value_;
}
iterator& operator++() {
h_.resume();
if (h_.done()) {
h_ = nullptr;
}
return *this;
}
bool operator==(std::nullptr_t) const noexcept {
return h_ == nullptr;
}
bool operator!=(std::nullptr_t) const noexcept {
return h_ != nullptr;
}
};

_generator(_generator&& other) noexcept : handle_(other.handle_) {
_generator() = default;
explicit _generator(handle_type h) : handle_(h) { }
_generator(_generator&& other) : handle_(other.handle_) {
other.handle_ = nullptr;
}
_generator& operator=(_generator&& other) noexcept {
_generator& operator=(_generator&& other) {
if (this != &other) {
Comment on lines +16 to 20
if (handle_) {
handle_.destroy();
Expand All @@ -50,14 +26,13 @@ namespace ds {
}
return *this;
}

~_generator() {
if (handle_) {
handle_.destroy();
}
}

iterator begin() {
iterator_type begin() {
if (!handle_) {
return {nullptr};
}
Expand All @@ -67,42 +42,54 @@ namespace ds {
}
return {handle_};
}
std::nullptr_t end() {
return nullptr;
iterator_type end() {
return {nullptr};
}

private:
_generator() noexcept : handle_(nullptr) { }
explicit _generator(handle_type h) noexcept : handle_(h) { }
friend class _generator_promise<T>;
};
struct promise_type {
T value_;

template<typename T>
class _generator_promise {
public:
T value_;
_generator<T> get_return_object() {
return _generator<T>(handle_type::from_promise(*this));
}
std::suspend_always initial_suspend() {
return {};
}
std::suspend_always final_suspend() noexcept {
return {};
}
std::suspend_always yield_value(T value) {
value_ = value;
return {};
Comment on lines +61 to +63
}
void unhandled_exception() {
throw;
}
Comment on lines +65 to +67
void return_void() { }
};

_generator<T> get_return_object() noexcept {
return _generator<T>(std::coroutine_handle<_generator_promise>::from_promise(*this));
}
std::suspend_always initial_suspend() noexcept {
return {};
}
std::suspend_always final_suspend() noexcept {
return {};
}
std::suspend_always yield_value(T& value) noexcept {
value_ = value;
return {};
}
std::suspend_always yield_value(T&& value) noexcept {
value_ = std::move(value);
return {};
}
void return_void() noexcept { }
void unhandled_exception() {
std::terminate();
}
struct iterator_type {
handle_type h_;

T& operator*() const {
return h_.promise().value_;
}
iterator_type& operator++() {
if (h_) {
h_.resume();
if (h_.done()) {
h_ = nullptr;
}
}
return *this;
}
bool operator==(const iterator_type& it) const {
return h_ == it.h_;
}
bool operator!=(const iterator_type& it) const {
return h_ != it.h_;
}
};
};

#if defined(__cpp_lib_generator) && 0
Expand All @@ -114,11 +101,4 @@ namespace ds {
#endif
} // namespace ds

namespace std {
template<typename T, typename... Args>
struct coroutine_traits<ds::_generator<T>, Args...> {
using promise_type = ds::_generator_promise<T>;
};
} // namespace std

#endif
Loading