Skip to content

Instantly share code, notes, and snippets.

@CaseyCarter
Created May 30, 2017 19:49
Show Gist options
  • Select an option

  • Save CaseyCarter/7b1b88f082506efa7026f9f2dfc529d2 to your computer and use it in GitHub Desktop.

Select an option

Save CaseyCarter/7b1b88f082506efa7026f9f2dfc529d2 to your computer and use it in GitHub Desktop.
#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