From 9c9221822a294021ecfccc28072cd4c3bfab5525 Mon Sep 17 00:00:00 2001 From: q66 Date: Sat, 11 Mar 2017 14:16:32 +0100 Subject: [PATCH] directly iterable generators --- examples/coroutine2.cc | 4 ++-- ostd/coroutine.hh | 46 ++++++++++++++++++++++++++++++++++++++++-- ostd/range.hh | 5 ----- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/examples/coroutine2.cc b/examples/coroutine2.cc index b9f8ecf..fcdf61c 100644 --- a/examples/coroutine2.cc +++ b/examples/coroutine2.cc @@ -4,14 +4,14 @@ using namespace ostd; int main() { - generator g = [](auto yield) { + auto f = [](auto yield) { for (int i: range(5, 26, 5)) { yield(i); } }; writeln("generator test"); - for (int i: g.iter()) { + for (int i: generator{f}) { writefln("generated: %s", i); } } diff --git a/ostd/coroutine.hh b/ostd/coroutine.hh index 6129e83..e775732 100644 --- a/ostd/coroutine.hh +++ b/ostd/coroutine.hh @@ -427,6 +427,10 @@ inline void swap(coroutine &a, coroutine &b) { template struct generator_range; +namespace detail { + template struct generator_iterator; +} + template struct generator: detail::coroutine_context { private: @@ -518,6 +522,10 @@ public: generator_range iter(); + /* for range for loop; they're the same, operator!= bypasses comparing */ + detail::generator_iterator begin(); + detail::generator_iterator end(); + void swap(generator &other) { using std::swap; swap(p_func, other.p_func); @@ -565,11 +573,10 @@ struct generator_range: input_range> { using value_type = T; using reference = T &; using size_type = size_t; - using difference_type = stream_off_t; + using difference_type = ptrdiff_t; generator_range() = delete; generator_range(generator &g): p_gen(&g) {} - generator_range(generator_range const &r): p_gen(r.p_gen) {} bool empty() const { return p_gen->empty(); @@ -595,6 +602,41 @@ generator_range generator::iter() { return generator_range{*this}; } +namespace detail { + /* deliberately incomplete, only for range for loop */ + template + struct generator_iterator { + generator_iterator() = delete; + generator_iterator(generator &g): p_gen(&g) {} + + bool operator!=(generator_iterator const &) { + return !p_gen->empty(); + } + + T &operator*() const { + return p_gen->value(); + } + + generator_iterator &operator++() { + p_gen->resume(); + return *this; + } + + private: + generator *p_gen; + }; +} /* namespace detail */ + +template +detail::generator_iterator generator::begin() { + return detail::generator_iterator{*this}; +} + +template +detail::generator_iterator generator::end() { + return detail::generator_iterator{*this}; +} + } /* namespace ostd */ #endif diff --git a/ostd/range.hh b/ostd/range.hh index 7fa4702..43d9f43 100644 --- a/ostd/range.hh +++ b/ostd/range.hh @@ -268,11 +268,6 @@ namespace detail { return get_ref().front(); } bool operator!=(range_iterator) const { return !get_ref().empty(); } - void swap(range_iterator &v) { - using std::swap; - swap(get_ref(). v.get_ref()); - swap(p_init, v.p_init); - } private: T &get_ref() { return *reinterpret_cast(&p_range); } T const &get_ref() const { return *reinterpret_cast(&p_range); }