#include #include #include #include #include #include class Fibonacci { struct end_t {}; public: // if we want read/write iterator, we can change this to: // template // class iterator_impl // and define: // using iterator = iterator_impl // using const_iterator = iterator_impl class iterator { public: using value_type = int; using reference = const int&; // this is const int&, because we defined const_iterator = iterator (const_iterator has to return readonly references) using pointer = const int*; // should be almost the same as the reference using difference_type = std::ptrdiff_t; // <- this has no meaning in our case, computing a difference is not that simple // using iterator_category = TODO: tag for forward iterators // TODO default constructor (iterators have to be default-constructible) iterator(int a0, int a1) : a0_{a0}, a1_{a1} {} const int& operator*() const { return a0_; } iterator& operator++() { int old_a0 = a0_; a0_ = a1_; a1_ = old_a0 + a1_; return *this; } // TODO: the post-increment iterator (creates a copy, increments *this, returns the copy) // an example of defaulting the == operator: (the compiler then also creates the != version) friend bool operator==(const iterator& left, const iterator& right) = default; private: int a0_, a1_; }; using const_iterator = iterator; [[nodiscard]] Fibonacci(int a0, int a1) : a0_{a0}, a1_{a1} {} [[nodiscard]] iterator begin() const { return iterator{a0_, a1_}; } [[nodiscard]] end_t end() const { return {}; } friend bool operator==([[maybe_unused]] const Fibonacci::iterator& it, [[maybe_unused]] const Fibonacci::end_t& end) { return false; } private: int a0_, a1_; }; static_assert(std::forward_iterator); static_assert(std::ranges::forward_range);