1009. InputIterator post-increment dangerous

Section: 24.3.5.2 [iterator.iterators] Status: NAD Submitter: Alisdair Meredith Opened: 2009-03-11 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [iterator.iterators].

View all issues with NAD status.

Discussion:

Addresses UK 251

The post-increment operator is dangerous for a general InputIterator. The multi-pass guarantees that make it meaningful are defined as part of the ForwardIterator refinement. Any change will affect only constrained templates that have not yet been written, so should not break existing user iterators which remain free to add these operations. This change will also affect the generalised OutputIterator, although there is no percieved need for the post-increment operator in this case either.

[ 2009-07-28 Alisdair adds: ]

We still think the issue is relevant, but needs totally rewording in non-concept language. We would like to see the issue retained as Open, rather than deferred as NAD Concepts. Review status is no longer appropriate.

[ 2009-10 Santa Cruz: ]

NAD. Without concepts we do not feel that input iterator post increment is broken.

Proposed resolution:

Change 24.3.5.2 [iterator.iterators]:

concept Iterator<typename X> : Semiregular<X> { 
  MoveConstructible reference = typename X::reference; 
  MoveConstructible postincrement_result;

  requires HasDereference<postincrement_result>;

  reference operator*(X&&); 
  X& operator++(X&); 
  postincrement_result operator++(X&, int);
}

...

postincrement_result operator++(X& r, int);

-3- Effects: equivalent to { X tmp = r; ++r; return tmp; }.

Change 24.3.5.3 [input.iterators]:

concept InputIterator<typename X> : Iterator<X>, EqualityComparable<X> { 
  ObjectType value_type = typename X::value_type; 
  MoveConstructible pointer = typename X::pointer; 

  SignedIntegralLike difference_type = typename X::difference_type; 

  requires IntegralType<difference_type> 
        && Convertible<reference, const value_type &>; 
        && Convertible<pointer, const value_type*>; 

  requires Convertible<HasDereference<postincrement_result>::result_type, const value_type&>;

  pointer operator->(const X&); 
}

Change 24.3.5.4 [output.iterators]:

auto concept OutputIterator<typename X, typename Value> { 
  requires Iterator<X>; 

  typename reference = Iterator<X>::reference; 
  typename postincrement_result = Iterator<X>::postincrement_result;
  requires SameType<reference, Iterator<X>::reference> 
        && SameType<postincrement_result, Iterator<X>::postincrement_result>
        && Convertible<postincrement_result, const X&>
        && HasAssign<reference, Value> 
        && HasAssign<HasDereference<postincrement_result>::result_type, Value>;
}

Change 24.3.5.5 [forward.iterators]:

[ See 1084 which is attempting to change this same area in a compatible way. ]

concept ForwardIterator<typename X> : InputIterator<X>, Regular<X> { 
  requires Convertible<postincrement_result, const X&>;

  MoveConstructible postincrement_result;
  requires HasDereference<postincrement_result>
        && Convertible<HasDereference<postincrement_result>::result_type, const value_type&>;

  postincrement_result operator++(X&, int);

  axiom MultiPass(X a, X b) { 
    if (a == b) *a == *b; 
    if (a == b) ++a == ++b; 
  } 
}

-4- ...

postincrement_result operator++(X& r, int);

-5- Effects: equivalent to { X tmp = r; ++r; return tmp; }.