Open melton1968 opened 2 years ago
I implemented generator_view
(modeled from istream_view
) which allows me to write the following code:
coro::Generator<int> counter(int n) {
for (auto i = 0; i < n; ++i)
co_yield i;
}
auto g = ranges::generator_view(counter(7));
auto h = g | v::take(5);
for (auto s : h)
cout << s << endl;
Feedback on whether this is a good path is appreciated. Maybe there is better view to use as a model?
The implementation of generator_view
follows:
namespace ranges
{
template<class T, class U = std::remove_cvref_t<T>>
struct generator_view : view_facade<generator_view<T, U>, unknown> {
private:
friend range_access;
coro::Generator<T, U> gen_;
semiregular_box_t<U> obj_;
struct cursor {
private:
friend range_access;
using single_pass = std::true_type;
generator_view *rng_ = nullptr;
public:
cursor() = default;
explicit cursor(generator_view *rng)
: rng_(rng) {
}
void next() { rng_->next(); }
T& read() const noexcept { return rng_->cached(); }
bool equal(default_sentinel_t) const { return rng_->gen_.done(); }
};
void next() {
gen_.next();
cached() = gen_();
}
cursor begin_cursor() { return cursor{this}; }
public:
generator_view() = default;
explicit generator_view(coro::Generator<T>&& gen)
: gen_(std::move(gen)) {
next();
}
T& cached() noexcept { return obj_; }
};
namespace _generator_
{
template<class T, class U = std::remove_cvref_t<T>>
requires copy_constructible<U> && default_constructible<U>
inline generator_view<T,U> generator(coro::Generator<T,U>&& gen) {
return generator_view<T,U>{std::move(gen)};
}
}; // _generator_
using namespace _generator_;
}; // ranges
I am using clang-11 with the latest version of range-v3 and a generator implementation that follows P2168. Should this in principle work?
The code:
generates the following completion error:
The generator implementation: