Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are Forward-Iterators Output-Iterators?

Are ForwardIterators required to be OutputIterators? My current STL-implementation (VS2012) derives forward_iterator_tag from both input_iterator_tag and output_iterator_tag, but I can't find this requirement in the standard [N3485].

like image 752
MFH Avatar asked Dec 27 '12 17:12

MFH


People also ask

What are forward iterators?

Forward iterators are used to read the contents from the beginning to the end of a container. Forward iterator use only increments operator (++) to move through all the elements of a container. Therefore, we can say that the forward iterator can only move forward. A Forward iterator is a multi-pass iterator.

What are output iterators?

An Output Iterator is a type that provides a mechanism for storing (but not necessarily accessing) a sequence of values.

What are the three main kinds of iterators?

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

What is the main difference between a forward iterator and bidirectional iterator?

C++ provides two non-const iterators that move in both the directions are iterator and reverse iterator. C++ Bidirectional iterator has the same features like the forward iterator, with the only difference is that the bidirectional iterator can also be decremented.


1 Answers

In C++11, no, forward iterators are not required to be output iterators. The output iterator requirements are like an extra set of requirements that an iterator can have, regardless of the rest of the iterator requirements it meets. Forward iterators are only required to be input iterators (§24.2.5/1):

A class or pointer type X satisfies the requirements of a forward iterator if:

  • X satisfies the requirements of an input iterator
  • ...

In fact, a forward iterator meets the output iterator requirements only if it is a mutable iterator to a sequence of copy-assignable types.

† or a constant iterator to a sequence of types with operator=(...) const defined with mutable members.

More to the point, the iterator tags are defined specifically by the standard as (§24.4.3/2):

namespace std {
  struct input_iterator_tag { };
  struct output_iterator_tag { };
  struct forward_iterator_tag: public input_iterator_tag { };
  struct bidirectional_iterator_tag: public forward_iterator_tag { };
  struct random_access_iterator_tag: public bidirectional_iterator_tag { };
}

As you can see, forward_iterator_tag should only inherit from input_iterator_tag.


In C++03, it is stated that forward iterators satisfy the requirements of input and output iterators:

Forward iterators satisfy all the requirements of the input and output iterators and can be used whenever either kind is specified.

But this is then contradicted in the following paragraph, stating that a constant forward iterator would not satisfy the requirements for output iterators:

Besides its category, a forward, bidirectional, or random access iterator can also be mutable or constant depending on whether the result of the expression *i behaves as a reference or as a reference to a constant. Constant iterators do not satisfy the requirements for output iterators, and the result of the expression *i (for constant iterator i) cannot be used in an expression where an lvalue is required.

However, the definition of the iterator tags is identical to as in C++11. There was a defect report for this contradictory wording, but it was closed as Not a Defect because the first quote is in the "introductory text" of the section and would likely be reworded in the future (which it was).


The SGI definition of a forward iterator is given as a refinement of both input and output iterators (thanks to @BenVoigt in the comments).

Nonetheless, if we take a look at the implementation of the iterator tags, we find that forward_iterator_tag still only inherits from input_iterator_tag.

Looks like this has been an area of quite a bit of confusion in the past, but if VS2012 is defining forward_iterator_tag as inheriting from both output_- and input_iterator_tag, I can only assume it is a bug.

like image 130
Joseph Mansfield Avatar answered Oct 10 '22 06:10

Joseph Mansfield