c++iterator-traits

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].


Solution

  • 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.