fibonacci.cpp

#include <coroutine>
#include <iostream>
#include <cstdint>

class Fibonacci
{
public:
    class promise_type
    {
    public: // customization of coro behavior
        Fibonacci get_return_object() { return Fibonacci(this); }
        std::suspend_never initial_suspend() noexcept { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        std::suspend_always yield_value(uint64_t elem)
        {
            _elem = elem;
            return {};
        }
        void unhandled_exception() {}

    public:
        uint64_t elem() const { return _elem; }
    private:
        uint64_t _elem{666};
    };

    using Handle = std::coroutine_handle<promise_type>;

public:
    explicit Fibonacci(promise_type* p) : _coro(Handle::from_promise(*p)) {}
    ~Fibonacci()
    { 
        if (_coro)
            _coro.destroy();
    }

    uint64_t next() const { return _coro.promise().elem(); }
    void resume() { _coro.resume(); }

private:
    Handle _coro{};
};

Fibonacci fibonacci()
{
    uint64_t first = 1;
    uint64_t second = 1;

    co_yield first;                                    // <--- suspend
    co_yield second;                                   // <--- suspend

    while (true) {
        uint64_t third = first + second;

        co_yield third;                                // <--- suspend
        
        first = second;
        second = third;
    }
}

int main()
{
    auto fibo = fibonacci();

    for (;;) {
        std::cout << fibo.next() << std::endl;
        fibo.resume();
    }

    return 0;
}