With C++11, the STL has now a std::iota
function (see a reference). In contrast to std::fill_n
, std::generate_n
, there is no std
You're so focused on code generation that you forgot to get the interface right.
You correctly require OutputIterator
, but what happens if you want to call it a second time?
list list(2 * N);
iota_n(list.begin(), N, 0);
// umm...
iota_n(list.begin() + N, N, 0); // doesn't compile!
iota_n(list.rbegin(), N, 0); // works, but create 0..N,N-1..0, not 0..N,0..N
auto it = list.begin();
std::advance(it, N);
iota_n(it, N, 0); // works, but ... yuck and ... slow (O(N))
inside iota_n
, you still know where you are, but you've thrown that information away, so the caller cannot get at it in constant time.
General principle: don't throw away useful information.
template
auto iota_n(OutputIterator dest, SizeType N, ValueType value) {
while (N) {
*dest = value;
++dest;
++value;
--N;
}
// now, what do we know that the caller might not know?
// N? No, it's zero.
// value? Maybe, but it's just his value + his N
// dest? Definitely. Caller cannot easily compute his dest + his N (O(N))
// So, return it:
return dest;
}
With this definition, the above example becomes simply:
list list(2 * N);
auto it = iota_n(list.begin(), N, 0);
auto end = iota_n(it, N, 0);
assert(end == list.end());