File: recursivegenerator.h

package info (click to toggle)
c%2B%2B-annotations 12.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 13,044 kB
  • sloc: cpp: 24,337; makefile: 1,517; ansic: 165; sh: 121; perl: 90
file content (95 lines) | stat: -rw-r--r-- 2,920 bytes parent folder | download | duplicates (2)
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