1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
#ifndef INCLUDED_RECURSIVEGENERATOR_H_
#define INCLUDED_RECURSIVEGENERATOR_H_
#include "promisebase.h"
#include "recursiveiterator.h"
template<typename T>
class [[nodiscard]] RecursiveGenerator
{
class Promise: public PromiseBase // final
{
using Handle = std::coroutine_handle<Promise>;
class Awaitable
{
Promise *d_childPromise;
public:
Awaitable(Promise *childPromise);
bool await_ready() noexcept;
void await_resume();
static void await_suspend(Handle) noexcept;
};
// If this is the promise of the root Generator then this field
// is a pointer to the leaf promise.
// For non-root Generators this is a pointer to the parent
// promise:
Promise *d_parentOrLeaf;
T *d_value = 0;
std::exception_ptr d_exception = 0;
Promise *d_root;
public:
Promise() noexcept;
Promise(Promise const &) = delete;
auto get_return_object() noexcept;
void unhandled_exception() noexcept;
std::suspend_always yield_value(T &&value) noexcept;
std::suspend_always yield_value(T &value) noexcept;
auto yield_value(RecursiveGenerator &generator) noexcept;
auto yield_value(RecursiveGenerator &&generator) noexcept;
void destroy() noexcept;
void throw_if_exception();
bool is_complete() noexcept;
T &value() noexcept;
void pull() noexcept;
// no 'co_await' inside the RecursiveGenerator coroutine.
template<typename U>
std::suspend_never await_transform(U&& value) = delete;
private:
void resume() noexcept;
};
Promise *d_promise;
public:
using promise_type = Promise;
RecursiveGenerator() noexcept = default;
RecursiveGenerator(Promise &promise) noexcept;
RecursiveGenerator(RecursiveGenerator &&tmp) noexcept;
~RecursiveGenerator();
RecursiveGenerator &operator=(RecursiveGenerator &&other)
noexcept;
RecGenIterator<T, Promise> begin();
RecGenIterator<T, Promise> end() noexcept;
void swap(RecursiveGenerator &other) noexcept;
};
// Note: When applying fmap operator to a RecursiveGenerator we just yield
// a non-recursive Generator since we generally won't be using the result
// in a recursive context.
template<typename FUNC, typename T>
Generator<
std::invoke_result_t<
FUNC &, typename RecursiveGenerator<T>::RecGenIterator::reference
>
> fmap(FUNC func, RecursiveGenerator<T> source);
#include "recursivepromise.imp"
#include "recursivegenerator.imp"
#include "recursiveiterator.imp"
#endif
|