An iterator which behaves like an array with uniform values 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 &lt;stdexcept&gt;
#include &lt;iterator&gt;
#include &lt;cstddef&gt;

template &lt;typename E&gt;
struct iterate_n_wrapper : public std::iterator&lt;std::input_iterator_tag, E, size_t&gt; {
    iterate_n_wrapper() = delete; // ... so it doesn't meet the forward iterator requirements
    iterate_n_wrapper(const iterate_n_wrapper&lt;E&gt;&amp; other) = default;
    iterate_n_wrapper(const E&amp; datum_, size_t times_)
        : datum(datum_), times(times_), pos(0) { };

    const E &amp; operator[](off_t offset) const {
        auto offset_pos = pos + offset;
        if (offset_pos &gt;= 0 &amp;&amp; offset_pos &lt; times) { return datum; }
        throw std::out_of_range("iteration range exceeded");
    }

    const E &amp; operator *() const { return operator[](0); }
    const E * operator -&gt;() const { return &amp;(operator *()); }

    iterate_n_wrapper&amp; operator ++() { pos++; return *this; }
    iterate_n_wrapper&amp; 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 &amp;other) const {
        return
            datum == other.datum &amp;&amp;
            times == other.times &amp;&amp;
            pos   == other.pos;
    }
    bool operator !=(const iterate_n_wrapper &amp;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&lt;int&gt; iwa(a, 6);
    for(int i = 0; i &lt; 4; i++) { 
         std::cout &lt;&lt; "iwa[" &lt;&lt; i &lt;&lt; "] = " &lt;&lt; iwa[i] &lt;&lt; "\n"; 
    }
    for(int i = 0; i &lt; 100; i++) {
        std::cout &lt;&lt; "i = " &lt;&lt; i &lt;&lt; ", got " &lt;&lt; *(iwa++) &lt;&lt; "\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.
As I alluded to in my question in the comments I think you should consider having a past-the-end iterator that would allow your iterator to be used with standard algorithms. Example:

std::copy(iterate_n_wrapper&lt;int&gt;(42, 4), iterate_n_wrapper&lt;int&gt;(), std::ostream_iterator&lt;int&gt;(std::cout, " "));


See std::istream_iterator for an example from the standard library of this concept in action.

cppreference.com has a nice example of how to achieve this.

It doesn't seem like an iterator is actually required to implement "past-the-endness" (note: I haven't dug into the standard to check), but it's something I, and I think most other C++ users, would expect. And the text in the link strongly hints that it's expected.

Normally you'd only supply operator* for an iterator and not operator[], but that's up to you.

Also I don't see a reason for using size_t as the difference_type (third template parameter to std::iterator) - why not stick with the default of std::ptrdiff_t?

You also need to implement Swapability for it to be satisfy the iterator concept.

Except for the missing past-the-end iterator, these are all minor quibbles. Building on std::iterator is was until C++17 (see @Olzhas comment) the right choice and I don't see anything wrong with the rest of your implementation.