3308. vector and deque iterator erase invalidates elements even when no change occurs

Section: 23.3.5.4 [deque.modifiers], 23.3.11.5 [vector.modifiers] Status: New Submitter: Billy O'Neal III Opened: 2019-10-29 Last modified: 2019-11-04

Priority: 3

View other active issues in [deque.modifiers].

View all other issues in [deque.modifiers].

View all issues with New status.

Discussion:

It seems incorrect that a container would invalidate anything as a result of being asked to erase 0 elements. This came up in a recent customer bug report against Visual Studio, where given a vector v, v.erase(v.begin(), v.begin()) triggered a self-assignment of all the elements in the vector.

deque has language enumerating erasures of the first and last element which invalidate fewer iterators, and a fallback that says all iterators are invalidated, which seems to intend to be talking about middle-of-container erasures. However, erasing 0 elements isn't really a middle of container erasure.

vector says that iterators and references are invalidated after the 'point of the erase', but when 0 elements are erased it's unclear what that even means.

We should say that erasures that erase 0 elements are no ops and be clearer about which elements are invalidated for vector.

[2019-11 Priority to 3 during Monday issue prioritization in Belfast]

Proposed resolution:

This wording is relative to N4835.

  1. Modify 23.3.5.4 [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: Erases elements as indicated in Table 75 [tab:container.seq.req]. 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 any elements, but 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. Modify 23.3.11.5 [vector.modifiers] as indicated:

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

    -3- Effects: Erases elements as indicated in Table 75 [tab:container.seq.req]. Invalidates iterators and references at or after the point of the erase.first erased element. [Note: For the second overload of erase, if first == last, no elements are erased, and no iterators or references are invalidated. — end note]

    […]