Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What iterator does vector::erase() return if passed an empty range?

According to cppreference.com and cplusplus.com, the function std::erase(first, last) returns "an iterator following the last removed element".

However, it is unclear what the return value is in the special case when there is no removed element at all, that is, when first == last (empty range). As of Jan 19, 2020, none of the above sources mention this special case.

For example, in the following code:

std::vector<int> v{1, 2, 3, 4};
auto it1 = v.erase(v.begin(), v.begin());
auto it2 = v.erase(v.end(), v.end());

What will be the value of it1 and it2?

like image 875
Boris Dalstein Avatar asked Jan 19 '20 22:01

Boris Dalstein


People also ask

Does vector erase return value?

If there is no such element (erased the last element in the vector) then it returns end() .

What happens to iterator after erase?

Every iterator and reference after the point of erasing is invalidated. Only the iterators and references to the erased element is invalidated. Only iterators and references to the erased elements are invalidated.

What does vector erase do?

vector::erase Erases the specified elements from the container. 1) Removes the element at pos . 2) Removes the elements in the range [first, last) . Invalidates iterators and references at or after the point of the erase, including the end() iterator.


1 Answers

This is specified in [sequence.reqmts]:

The iterator returned by a.erase(q1, q2) points to the element pointed to by q2 prior to any elements being erased. If no such element exists, a.end() is returned.

(Note: I linked the C++17 final working draft, but this wording exists since at least C++98, see comment by @Peter)

So we should have it1 == v.begin() and it2 == v.end().

Live test:

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{1, 2, 3, 4};
    auto it1 = v.erase(v.begin(), v.begin());
    auto it2 = v.erase(v.end(), v.end());
    std::cout << std::distance(v.begin(), it1) << std::endl;
    std::cout << std::distance(v.begin(), it2) << std::endl;
}

Output:

0
4

To clarify this behavior, I have updated the cppreference documentation, which is now:

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

Return Value

Iterator following the last removed element.

If pos refers to the last element, then the end() iterator is returned.

If last==end() prior to removal, then the updated end() iterator is returned.

If [first, last) is an empty range, then last is returned.

like image 60
Boris Dalstein Avatar answered Oct 21 '22 02:10

Boris Dalstein