Series: Iterator, Iterator Wrapper, Non-1-1 Wrapper
To make your own iterable range in C++ that you can loop over or make a vector out of (mine is called Numbers):
// Prints:
// 3,4,
for (auto n : Numbers(3, 5))
{
std::cout << n << ",";
}
// Fills vec with 7, 8, 9
Numbers nums(7, 10);
std::vector vec{std::begin(nums), std::end(nums)};
you need to write a class that is an Input Iterator, and provide an instance as the begin and end of your range:
class Numbers
{
private:
const int start_;
const int end_;
public:
Numbers(int start, int end) : start_(start) , end_(end) {}
myit begin() { return myit(start_); }
myit end() { return myit(end_); }
};
The hard bit is the Input Iterator:
#include <iterator>
class myit
{
private:
int value_;
class intholder
{
int value_;
public:
intholder(int value): value_(value) {}
int operator*() { return value_; }
};
public:
// Previously provided by std::iterator - see update below
typedef int value_type;
typedef std::ptrdiff_t difference_type;
typedef int* pointer;
typedef int& reference;
typedef std::input_iterator_tag iterator_category;
explicit myit(int value) : value_(value) {}
int operator*() const { return value_; }
bool operator==(const myit& other) const { return value_ == other.value_; }
bool operator!=(const myit& other) const { return !(*this == other); }
intholder operator++(int)
{
intholder ret(value_);
++*this;
return ret;
}
myit& operator++()
{
++value_;
return *this;
}
};
Update: thanks to Anthony Williams for the correction on the postincrement operator – see Generating Sequences for more. Note the need to return a fiddly object that holds the answer we will give when the return value is dereferenced.
Using std::iterator as a base class actually only gives you some typedefs for free, but it’s worth it to get the standard names, and to be clear what we are trying to do. Update: std::iterator is deprecated in C++17 – just add the 5 typedefs yourself.
I suspect I might need to add some extra &s to make this good C++11 style?
C++ iterator example (and an iterable range)
Sadly, your postincrement operator isn’t right.
The requirement on postincrement is that *it++ returns the value at the iterator before the increment. Returning value_type from the postincrement operator doesn’t work for that: you would need to write just it++, which would be odd.
I explained how to write an iterator for exactly this scenario (numeric ranges) on my blog a couple of months ago: https://www.justsoftwaresolutions.co.uk/cplusplus/generating_sequences.html
Thanks Anthony – I wish I’d found your post when I was researching this. I was kind of hoping I’d get some corrections if I posted this!