forked from OctaForge/libostd
directly iterable generators
parent
058efff580
commit
9c9221822a
|
@ -4,14 +4,14 @@
|
||||||
using namespace ostd;
|
using namespace ostd;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
generator<int> g = [](auto yield) {
|
auto f = [](auto yield) {
|
||||||
for (int i: range(5, 26, 5)) {
|
for (int i: range(5, 26, 5)) {
|
||||||
yield(i);
|
yield(i);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
writeln("generator test");
|
writeln("generator test");
|
||||||
for (int i: g.iter()) {
|
for (int i: generator<int>{f}) {
|
||||||
writefln("generated: %s", i);
|
writefln("generated: %s", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -427,6 +427,10 @@ inline void swap(coroutine<R(A...)> &a, coroutine<R(A...)> &b) {
|
||||||
|
|
||||||
template<typename T> struct generator_range;
|
template<typename T> struct generator_range;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template<typename T> struct generator_iterator;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct generator: detail::coroutine_context {
|
struct generator: detail::coroutine_context {
|
||||||
private:
|
private:
|
||||||
|
@ -518,6 +522,10 @@ public:
|
||||||
|
|
||||||
generator_range<T> iter();
|
generator_range<T> iter();
|
||||||
|
|
||||||
|
/* for range for loop; they're the same, operator!= bypasses comparing */
|
||||||
|
detail::generator_iterator<T> begin();
|
||||||
|
detail::generator_iterator<T> end();
|
||||||
|
|
||||||
void swap(generator &other) {
|
void swap(generator &other) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(p_func, other.p_func);
|
swap(p_func, other.p_func);
|
||||||
|
@ -565,11 +573,10 @@ struct generator_range: input_range<generator_range<T>> {
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
using reference = T &;
|
using reference = T &;
|
||||||
using size_type = size_t;
|
using size_type = size_t;
|
||||||
using difference_type = stream_off_t;
|
using difference_type = ptrdiff_t;
|
||||||
|
|
||||||
generator_range() = delete;
|
generator_range() = delete;
|
||||||
generator_range(generator<T> &g): p_gen(&g) {}
|
generator_range(generator<T> &g): p_gen(&g) {}
|
||||||
generator_range(generator_range const &r): p_gen(r.p_gen) {}
|
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
return p_gen->empty();
|
return p_gen->empty();
|
||||||
|
@ -595,6 +602,41 @@ generator_range<T> generator<T>::iter() {
|
||||||
return generator_range<T>{*this};
|
return generator_range<T>{*this};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
/* deliberately incomplete, only for range for loop */
|
||||||
|
template<typename T>
|
||||||
|
struct generator_iterator {
|
||||||
|
generator_iterator() = delete;
|
||||||
|
generator_iterator(generator<T> &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<T> *p_gen;
|
||||||
|
};
|
||||||
|
} /* namespace detail */
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
detail::generator_iterator<T> generator<T>::begin() {
|
||||||
|
return detail::generator_iterator<T>{*this};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
detail::generator_iterator<T> generator<T>::end() {
|
||||||
|
return detail::generator_iterator<T>{*this};
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace ostd */
|
} /* namespace ostd */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -268,11 +268,6 @@ namespace detail {
|
||||||
return get_ref().front();
|
return get_ref().front();
|
||||||
}
|
}
|
||||||
bool operator!=(range_iterator) const { return !get_ref().empty(); }
|
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:
|
private:
|
||||||
T &get_ref() { return *reinterpret_cast<T *>(&p_range); }
|
T &get_ref() { return *reinterpret_cast<T *>(&p_range); }
|
||||||
T const &get_ref() const { return *reinterpret_cast<T const *>(&p_range); }
|
T const &get_ref() const { return *reinterpret_cast<T const *>(&p_range); }
|
||||||
|
|
Loading…
Reference in New Issue