Created
May 30, 2017 19:49
-
-
Save CaseyCarter/7b1b88f082506efa7026f9f2dfc529d2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <utility> | |
| #include <experimental/coroutine> | |
| #include <range/v3/view_facade.hpp> | |
| #include <range/v3/view/all.hpp> | |
| namespace ranges | |
| { | |
| inline namespace v3 | |
| { | |
| struct generator : view_facade<generator> | |
| { | |
| struct promise_type | |
| { | |
| int value_ = 42; | |
| generator get_return_object() | |
| { | |
| return generator{*this}; | |
| } | |
| std::experimental::suspend_always initial_suspend() const noexcept | |
| { | |
| return {}; | |
| } | |
| std::experimental::suspend_always final_suspend() const noexcept | |
| { | |
| return {}; | |
| } | |
| void return_void() const noexcept | |
| {} | |
| void unhandled_exception() noexcept | |
| {} | |
| std::experimental::suspend_always yield_value(int i) noexcept | |
| { | |
| value_ = i; | |
| return {}; | |
| } | |
| }; | |
| using handle = std::experimental::coroutine_handle<promise_type>; | |
| static void advance(handle coro) | |
| { | |
| RANGES_EXPECT(coro); | |
| RANGES_EXPECT(!coro.done()); | |
| coro.resume(); | |
| } | |
| struct cursor | |
| { | |
| handle coro_{}; | |
| cursor() = default; | |
| constexpr explicit cursor(handle coro) noexcept | |
| : coro_{coro} | |
| {} | |
| bool equal(default_sentinel) const | |
| { | |
| RANGES_EXPECT(coro_); | |
| return coro_.done(); | |
| } | |
| void next() | |
| { | |
| generator::advance(coro_); | |
| } | |
| int read() const | |
| { | |
| RANGES_EXPECT(coro_); | |
| return coro_.promise().value_; | |
| } | |
| }; | |
| ~generator() | |
| { | |
| if (coro_) coro_.destroy(); | |
| } | |
| generator() = default; | |
| explicit generator(promise_type &p) | |
| : coro_{handle::from_promise(p)} | |
| {} | |
| generator(generator &&that) noexcept | |
| : coro_{that.coro_} | |
| { | |
| that.coro_ = nullptr; | |
| } | |
| cursor begin_cursor() | |
| { | |
| generator::advance(coro_); | |
| return cursor{coro_}; | |
| } | |
| handle coro_{}; | |
| }; | |
| struct coro_fn | |
| { | |
| private: | |
| template<class V, CONCEPT_REQUIRES_(InputView<V>())> | |
| static generator impl(V v) | |
| { | |
| auto first = begin(v); | |
| auto const last = end(v); | |
| for (; first != last; ++first) | |
| co_yield *first; | |
| } | |
| public: | |
| template<class V, CONCEPT_REQUIRES_(InputView<V>())> | |
| generator operator()(V v) const | |
| { | |
| return impl(v); | |
| } | |
| }; | |
| RANGES_INLINE_VARIABLE(coro_fn, coro) | |
| } | |
| } | |
| #include <iostream> | |
| #include <range/v3/view/filter.hpp> | |
| #include <range/v3/view/iota.hpp> | |
| #include <range/v3/view/take_exactly.hpp> | |
| int main() | |
| { | |
| using namespace ranges; | |
| auto even = [](int i){ return i % 2 == 0; }; | |
| std::cerr << coro(view::take_exactly(view::filter(view::ints, even), 10)); | |
| std::cerr << '\n'; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment