I'm implementing an iterator which takes a single value and which you can advance for n times with a dereferencing yielding the single value - but before or after that range of n 'positions' you can't dereference. So it's as though you filled a length-n std::vector with a single value and were taking a const iterator over it.
Imlementation is intentionally not thread-safe.
#include <stdexcept>
#include <iterator>
#include <cstddef>
template <typename E>
struct iterate_n_wrapper : public std::iterator<std::input_iterator_tag, E, size_t> {
iterate_n_wrapper() = delete; // ... so it doesn't meet the forward iterator requirements
iterate_n_wrapper(const iterate_n_wrapper<E>& other) = default;
iterate_n_wrapper(const E& datum_, size_t times_)
: datum(datum_), times(times_), pos(0) { };
const E & operator[](off_t offset) const {
auto offset_pos = pos + offset;
if (offset_pos >= 0 && offset_pos < times) { return datum; }
throw std::out_of_range("iteration range exceeded");
}
const E & operator *() const { return operator[](0); }
const E * operator ->() const { return &(operator *()); }
iterate_n_wrapper& operator ++() { pos++; return *this; }
iterate_n_wrapper& operator --() { pos--; return *this; }
iterate_n_wrapper operator ++(int) { auto ret = *this; operator++(); return ret; }
iterate_n_wrapper operator --(int) { auto ret = *this; operator--(); return ret; }
bool operator ==(const iterate_n_wrapper &other) const {
return
datum == other.datum &&
times == other.times &&
pos == other.pos;
}
bool operator !=(const iterate_n_wrapper &other) const { return !operator==(other); }
protected:
const E datum;
size_t times;
ptrdiff_t pos;
};
A simple example of use:
int main() {
int a = 123;
iterate_n_wrapper<int> iwa(a, 6);
for(int i = 0; i < 4; i++) {
std::cout << "iwa[" << i << "] = " << iwa[i] << "\n";
}
for(int i = 0; i < 100; i++) {
std::cout << "i = " << i << ", got " << *(iwa++) << "\n";
}
return 0;
}
produces:
iwa[0] = 123
iwa[1] = 123
iwa[2] = 123
iwa[3] = 123
i = 0, got 123
i = 1, got 123
i = 2, got 123
i = 3, got 123
i = 4, got 123
i = 5, got 123
terminate called after throwing an instance of 'std::out_of_range'
what(): iteration range exceeded
Aborted (core dumped)
so, the motivation is that this is a stand-in for an array/vector iterator when you can get the length from someplace else. Although I guess the lack of some kind of corresponding end() is a shortcoming.