03 | 写一个能产生斐波那契数列的range——惰性求值

发布时间 2023-04-23 11:36:35作者: 独立树

1.首先为了满足 range 概念的要求我们需要提供 begin() 和 end()
2.begin() 和 end() 返回的应该是迭代器,注意这个地方两种可以返回两种不同类型(c++17后即可)
3.为了满足迭代器 概念的要求我们提供5个 typedef,并根据 std::input_iterator_tag 类型决定我们要实现的“解引用函数”,“前后置++”,“比较函数”等。

#include <stddef.h>
#include <iostream>
#include <ranges>
#include <stdint.h>
#include <concepts>

class fibonacci {
public:
    class sentinel;
    class iterator;
    iterator begin() noexcept;
    sentinel end() noexcept;
};

class fibonacci::sentinel {};

class fibonacci::iterator {
public:
    // Required to satisfy iterator
    // concept
    typedef ptrdiff_t               difference_type;
    typedef uint64_t                value_type;
    typedef const uint64_t*         pointer;
    typedef const uint64_t&         reference;
    typedef std::input_iterator_tag iterator_category;
    value_type operator*() const
    {
        return b_;
    }
    pointer operator->() const
    {
        return &b_;
    }
    iterator& operator++()
    {
        auto tmp = a_;
        a_ = b_;
        b_ += tmp;
        return *this;
    }
    iterator operator++(int)
    {
        auto tmp = *this;
        ++*this;
        return tmp;
    }
    bool operator==(const sentinel&) const
    {
        return false;
    }
    bool operator!=(const sentinel&) const
    {
        return true;
    }

private:
    uint64_t a_{0};
    uint64_t b_{1};
};

// sentinel needs to be
// equality_comparable_with iterator

bool operator==(const fibonacci::sentinel& lhs,
                const fibonacci::iterator& rhs)
{
    return rhs == lhs;
}

bool operator!=(const fibonacci::sentinel& lhs,
                const fibonacci::iterator& rhs)
{
    return rhs != lhs;
}

inline fibonacci::iterator fibonacci::begin() noexcept
{
    return iterator();
}

inline fibonacci::sentinel fibonacci::end() noexcept
{
    return sentinel();
}


int main(){
    // 打印头20项
    for(auto i:fibonacci()|std::ranges::views::take(20)){
        std::cout<<i<<std::endl;
    }
    // 打印小于 10000 的数列项
    for(auto i:fibonacci()|
        std::ranges::views::take_while([](uint64_t x){
            return x<1000;
        })){
            std::cout<<i<<std::endl;
    }
}