Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STL fill and forward iterator

Tags:

c++

iterator

stl

According to most C++ references, for instance cplusplus.com, forward iterators are not required to be assignable (I mean, deferenced to an lvalue). However, for several STL algorithms that need to write values, for instance std::fill (also std::generate etc.), the specification uses forward iterator:

template <class ForwardIterator, class T>
  void fill (ForwardIterator first, ForwardIterator last, const T& val);

while the equivalent behavior requires lvalue dereference:

template <class ForwardIterator, class T>
  void fill (ForwardIterator first, ForwardIterator last, const T& val)
{
  while (first != last) {
    *first = val;
    ++first;
  }
}

So, it is actually using a mutable forward iterator with a single pass.

Now the questions are:

(1) Why not make it clear that the forward iterators used in these cases are mutable?

(2) Update: I found the following question to be stupid: I temporarily forgot that output iterators do not need to support equality comparison. The above question remains, anyway.

Why use forward iterators instead of output iterators for std::fill, std::generate etc. while they do not actually need multiple passes? (std::copy only needs output iterators, for instance. What's the rationale?)

like image 271
4ae1e1 Avatar asked Apr 29 '13 23:04

4ae1e1


2 Answers

From the signature

template <class ForwardIterator, class T>
void fill (ForwardIterator first, ForwardIterator last, const T& val);

you cannot infer that ForwardIterator is an iterator described in forward iterator. However, if you read the parameter description, you will find that first and last must be

Forward Iterators to the initial and final positions in a sequence of elements that support being assigned a value of type T.

(emphasis by me). So a forward iterator that fulfills nothing more than what is required of a forward iterator is not a valid argument.

like image 189
Oswald Avatar answered Sep 20 '22 08:09

Oswald


It doesn't seem terribly strange to me, given that the specification for fill is that the (dereferenced) iterator be assignable from T. An output iterator won't suffice because it's not comparable to determine the range end, so a forward_iterator with requirements was chosen.

You'll note that fill_n does use output iterators because no iterator comparison is needed to determine the end of the sequence to fill.

like image 33
Mark B Avatar answered Sep 19 '22 08:09

Mark B