srctree

Robin Linden parent 39d56b95 7f4b468e
util/generator: Support use in range-based for loops

inlinesplit
util/generator.h added: 56, removed: 2, total 54
@@ -64,6 +64,29 @@ public:
return v;
}
 
private:
struct CoroutineSentinel {
friend constexpr bool operator!=(auto const &generator_iterator, CoroutineSentinel const &) {
return !generator_iterator.handle.done();
}
};
 
struct GeneratorIterator {
Handle handle;
 
GeneratorIterator &operator++() {
handle.resume();
return *this;
}
 
T &operator*() const { return handle.promise().maybe_value.value(); }
T *operator->() const { return &**this; }
};
 
public:
GeneratorIterator begin() { return {handle_}; }
CoroutineSentinel end() { return {}; }
 
private:
Handle handle_{};
};
 
util/generator_test.cpp added: 56, removed: 2, total 54
@@ -90,5 +90,36 @@ int main() {
});
#endif
 
etest::test("range-based for loop", [] {
auto gen = []() -> util::Generator<char> {
co_yield 'a';
co_yield 'b';
co_yield 'c';
}();
 
char current_expectation = 'a';
for (auto c : gen) {
expect_eq(current_expectation, c);
++current_expectation;
}
 
expect_eq('d', current_expectation);
});
 
etest::test("boring for loop", [] {
auto gen = []() -> util::Generator<std::pair<char, int>> {
co_yield {'a', 2};
}();
 
int iterations{};
for (auto it = std::begin(gen); it != std::end(gen); ++it) {
expect_eq(it->first, 'a');
expect_eq(it->second, 2);
++iterations;
}
 
expect_eq(1, iterations);
});
 
return etest::run_all_tests();
}