In this section, we concentrate on implementing an iterator that generates numbers from the Fibonacci number sequence while iterating over it.
- In order to be able to print the Fibonacci numbers to the terminal, we need to include a header first:
#include <iostream>
- We call the Fibonacci iterator, fibit. It will carry a member i, which saves the index position in the Fibonacci sequence, and a and b will be the variables that hold the last two Fibonacci values. If instantiated with the default constructor, a Fibonacci iterator will be initialized to the value F(0):
class fibit
{
size_t i {0};
size_t a {0};
size_t b {1};
- Next, we define the standard constructor and another constructor, which allows us to initialize the iterator at any Fibonacci number step:
public:
fibit() = default;
explicit fibit(size_t i_)
: i{i_}
{}
- When dereferencing our iterator (*it), it will just emit the Fibonacci number of the current step:
size_t operator*() const { return b; }
- When incrementing the iterator (++it), it will move its state to the next Fibonacci number. This function contains the same code as the loop-based Fibonacci implementation:
fibit& operator++() {
const size_t old_b {b};
b += a;
a = old_b;
++i;
return *this;
}
- When used in a loop, the incremented iterator is compared against an end iterator, for which we need to define the != operator. We are only comparing the step at which the Fibonacci iterators currently reside, which makes it easier to define the end iterator for step 1000000, for example, as we do not need to expensively calculate such a high Fibonacci number in advance:
bool operator!=(const fibit &o) const { return i != o.i; }
};
- In order to be able to use the Fibonacci iterator in the range-based for loop, we have to implement a range class beforehand. We call it fib_range, and its constructor will accept one parameter that tells how far in the Fibonacci range we want to iterate:
class fib_range
{
size_t end_n;
public:
fib_range(size_t end_n_)
: end_n{end_n_}
{}
- Its begin and end functions return iterators which point to the positions, F(0) and F(end_n):
fibit begin() const { return fibit{}; }
fibit end() const { return fibit{end_n}; }
};
- Okay, now let's forget about all the iterator-related boilerplate code. We do not need to touch it again as we have a helper class now which nicely hides all the implementation details from us! Let's print the first 10 Fibonacci numbers:
int main()
{
for (size_t i : fib_range(10)) {
std::cout << i << ", ";
}
std::cout << 'n';
}
- Compiling and running the program yields the following shell output:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55,