Title
deque and vector pop_back don't specify iterator invalidation requirements
Status
c++17
Section
[deque.modifiers] [vector.modifiers]
Submitter
Deskin Miller

Created on 2014-02-17.00:00:00 last changed 90 months ago

Messages

Date: 2014-11-08.16:43:57

Proposed resolution:

This wording is relative to N3936.

  1. Change [deque.modifiers] as indicated:

    iterator erase(const_iterator position);
    iterator erase(const_iterator first, const_iterator last);
    void pop_front();
    void pop_back();
    

    -4- Effects: An erase operation that erases the last element of a deque invalidates only the past-the-end iterator and all iterators and references to the erased elements. An erase operation that erases the first element of a deque but not the last element invalidates only iterators and references to the erased elements. An erase operation that erases neither the first element nor the last element of a deque invalidates the past-the-end iterator and all iterators and references to all the elements of the deque. [Note: pop_front and pop_back are erase operations — end note]

  2. Change [vector.modifiers] as indicated:

    iterator erase(const_iterator position);
    iterator erase(const_iterator first, const_iterator last);
    void pop_back();
    

    -3- Effects: Invalidates iterators and references at or after the point of the erase.

Date: 2014-11-08.16:43:57

[ Urbana 2014-11-07: Move to Ready ]

Date: 2014-06-21.00:00:00

[ 2014-06-21 Rapperswil ]

Tony van Eerd: Would be good to define "an erase operation is ..." somewhere.

AM: The containers clause is known to be suboptimal in many ways.

Looks good

Date: 2014-06-16.00:00:00

[ 2014-06-16 Jonathan comments and improves wording ]

I believe this reflects our preferred form discussed earlier, specifically putting the signatures with the erase signatures, so that the full specification of erase() applies to the pop_xxx() functions. This covers the case for deque where pop_front() erases the only element (which is both the first and last element).

Open question: the "erase" wording talks about "An erase operation" — are pop_front and pop_back clearly covered by "erase operations"? I believe so, as [deque.overview]/1 and other places talk about "insert and erase operations" which covers push/pop functions too. I've added a note which could be used to clarify that if desired.

Previous resolution [SUPERSEDED]:

This wording is relative to N3936.

  1. Change [deque.modifiers] as indicated:

    iterator erase(const_iterator position);
    iterator erase(const_iterator first, const_iterator last);
    

    -4- Effects: An erase operation that erases the last element of a deque invalidates only the past-the-end iterator and all iterators and references to the erased elements. An erase operation that erases the first element of a deque but not the last element invalidates only iterators and references to the erased elements. An erase operation that erases neither the first element nor the last element of a deque invalidates the past-the-end iterator and all iterators and references to all the elements of the deque.

    -5- […]

    -6- […]

    void pop_front();
    void pop_back();
    

    -?- Effects: pop_front invalidates iterators and references to the first element of the deque. pop_back invalidates the past-the-end iterator, and all iterators and references to the last element of the deque.

  2. Change [vector.modifiers] as indicated:

    -5- […]

    void pop_back();
    

    -?- Effects: Invalidates the past-the-end iterator, and iterators and references to the last element of the vector.

Date: 2014-02-17.00:00:00

I think it's obvious that vector::pop_back invalidates the path-the-end iterator, but I cannot find language that says so to my satisfaction in the Standard. N3797 [sequence.reqmts] Table 101 lists a.pop_back() semantics as "Destroys the last element", but nowhere do I see this required to invalidate the end iterator (or iterators previously referring to the last element). [container.reqmts.general]/11 states "Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iterators to, or change the values of, objects within that container." [vector.modifiers]/3 says that each flavor of vector::erase "Invalidates iterators and references at or after the point of the erase", but pop_back isn't discussed, and it wasn't specified in terms of erase.

Similarly for std::deque, [sequence.reqmts] Table 101 and [container.reqmts.general]/11 both apply. Yet [deque.modifiers] likewise doesn't discuss pop_back nor pop_front. Furthermore paragraph 4 fails to specify the iterator-invalidation guarantees when erasing the first element but not the last.

Both std::vector and std::deque are in contrast to std::list, which says in [list.modifiers]/3 regarding pop_back (as well as all forms of erase, pop_front, and clear) "Effects: Invalidates only the iterators and references to the erased elements."

History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2015-05-22 18:31:21adminsetstatus: ready -> wp
2014-11-08 16:43:57adminsetmessages: + msg7172
2014-11-08 16:43:57adminsetstatus: review -> ready
2014-06-28 17:39:20adminsetmessages: + msg7074
2014-06-28 17:39:20adminsetstatus: open -> review
2014-06-22 18:04:10adminsetstatus: new -> open
2014-06-17 00:30:22adminsetmessages: + msg7056
2014-03-23 20:11:22adminsetmessages: + msg6903
2014-02-17 00:00:00admincreate