Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do iterators need to be default-constructible

Iterators of the categories forward, bidirectional, and random access need to be default-constructible.

Why is this, and why do input and output operators not have to be default-constructible?

like image 892
sbi Avatar asked Mar 03 '15 13:03

sbi


People also ask

What is default value of iterator in C++?

By convention a "NULL iterator" for containers, which is used to indicate no result, compares equal to the result of container. end() . However, since a default-constructed container iterator is not associated with any particular container, there is no good value it could take.

What are three main kinds of iterators?

There are three main kinds of input iterators: ordinary pointers, container iterators, and input streams iterators.

What are forward iterators?

Forward iterators are iterators that can be used to access the sequence of elements in a range in the direction that goes from its beginning towards its end. Performing operations on a forward iterator that is dereferenceable never makes its iterator value non-dereferenceable.


2 Answers

Forward iterators and stronger are required to refer to some external sequence (see [forward.iterators]/6 which says "If a and b are both dereferenceable, then a == b if and only if *a and *b are bound to the same object.")

This means they are generally just a lightweight handle onto something else (e.g. a pointer to an element or a node in a container) and so there is little reason not to require that they can be default constructed (even if default construction creates a singular iterator that can't be used for anything until assigned a new value). It's possible for all non-pathological* forward iterators to support default construction, and relying on that makes some algorithms easier to implement.

Iterators which only meet the input iterator or output iterator requirements (and nothing stronger) might contain state within themselves which is modified by operator++ and so it might not be possible for that state to be default-constructed. No algorithm that only operates on input/output iterators needs to default construct them, so it isn't required.

  • spot the "no true scotsman" argument here ;)
like image 54
Jonathan Wakely Avatar answered Oct 05 '22 01:10

Jonathan Wakely


reference for iterators

Input/Output iterators:

Input Iterator: once an InputIterator i has been incremented, all copies of its previous value may be invalidated.

Output Iterator: After this operation r is not required to be dereferenceable and any copies of the previous value of r are no longer required to be dereferenceable or incrementable.

If we look at this it seems clear that these iterators are designed to be used in the simplest method possible. Much like an array index or simple pointer would be used for single-pass algorithms. There is therefore really no need to have default constructors.

Note however that just because default constructors is not required technically doesn't disqualify you from implementing them if you want.

Forward iterators:

These are the first level of iterators that require default constructors but why?

There are many reasons related to historical programming reasons ect and I believe this is all to some extent valid. In a certain way I think the committee figured somewhere between iterator and randomAccessIterator default construction was required to be implemented and forward iterators seemed like the best choice.

There is however one fairly good reason why:

Forward iterators support multi-pass algorithms and therefore require that copies of the iterator are still valid after the iterator has been used/incremented. If these copies are valid still it means the algorithm would allow us to "save" them somewhere. Which also means the iterator where we save them needs to have a default/initial value.

Consider:

class MyClass {  public:   void myFunction(ForwardIterator &i)   {     //do some code here     savedIter = i;     //do some code here   }  private:   ForwardIterator savedIter; } 

By definition this is valid because we are allowed to save the iterator for some amount of time as the requirement is that copies of this iterator will remain valid. (At least until the data structure the iterator points to is destroyed)

However for this class to be created ForwardIterator requires a default constructor obviously...

like image 43
Heinrich du Toit Avatar answered Oct 05 '22 00:10

Heinrich du Toit