parent
689bb150c6
commit
f668ff6b7a
@ -0,0 +1,97 @@ |
|||||||
|
#include <coroutine> |
||||||
|
#include <cstdint> |
||||||
|
#include <exception> |
||||||
|
#include <fmt/core.h> |
||||||
|
|
||||||
|
|
||||||
|
template<typename T> |
||||||
|
struct Generator { |
||||||
|
struct promise_type; |
||||||
|
using handle_type = std::coroutine_handle<promise_type>; |
||||||
|
|
||||||
|
struct promise_type { |
||||||
|
T value_; |
||||||
|
std::exception_ptr exception_; |
||||||
|
|
||||||
|
Generator get_return_object() { |
||||||
|
return Generator(handle_type::from_promise(*this)); |
||||||
|
} |
||||||
|
std::suspend_always initial_suspend() { return {}; } |
||||||
|
std::suspend_always final_suspend() noexcept { return {}; } |
||||||
|
void unhandled_exception() { exception_ = std::current_exception(); } |
||||||
|
|
||||||
|
template<std::convertible_to<T> From> |
||||||
|
std::suspend_always yield_value(From&& from) { |
||||||
|
value_ = std::forward<From>(from); |
||||||
|
return {}; |
||||||
|
} |
||||||
|
void return_void() {} |
||||||
|
}; |
||||||
|
|
||||||
|
handle_type h_; |
||||||
|
|
||||||
|
Generator(handle_type h) : h_(h) {} |
||||||
|
~Generator() { h_.destroy(); } |
||||||
|
explicit operator bool() { |
||||||
|
fill(); |
||||||
|
return !h_.done(); |
||||||
|
} |
||||||
|
|
||||||
|
T operator()() { |
||||||
|
fill(); |
||||||
|
full_ = false; |
||||||
|
return std::move(h_.promise().value_); |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
bool full_ = false; |
||||||
|
|
||||||
|
void fill() { |
||||||
|
if(!full_) { |
||||||
|
h_(); |
||||||
|
if(h_.promise().exception_) { |
||||||
|
std::rethrow_exception(h_.promise().exception_); |
||||||
|
} |
||||||
|
|
||||||
|
full_ = true; |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
Generator<std::uint64_t> |
||||||
|
fib(unsigned n) { |
||||||
|
if(n == 0) co_return; |
||||||
|
if(n > 94) { |
||||||
|
throw std::runtime_error("Too big"); |
||||||
|
} |
||||||
|
|
||||||
|
if(n == 1) co_return; |
||||||
|
|
||||||
|
co_yield 1; |
||||||
|
|
||||||
|
if(n == 2) co_return; |
||||||
|
|
||||||
|
std::uint64_t a = 0; |
||||||
|
std::uint64_t b = 1; |
||||||
|
for(unsigned i = 2; i < n; ++i) { |
||||||
|
std::uint64_t s = a + b; |
||||||
|
co_yield s; |
||||||
|
a = b; |
||||||
|
b = s; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int main() { |
||||||
|
try { |
||||||
|
auto gen = fib(50); |
||||||
|
for(int j = 0; gen; ++j) { |
||||||
|
fmt::println("fib({})={}", j, gen()); |
||||||
|
} |
||||||
|
} catch(const std::exception& ex) { |
||||||
|
fmt::println("Exception: {}", ex.what()); |
||||||
|
} catch(...) { |
||||||
|
fmt::println("Unknown exception"); |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
[ |
||||||
|
{"test": 0}, |
||||||
|
{"test": 1} |
||||||
|
] |
Loading…
Reference in new issue