3

I got this question when I was reading erase-remove idiom (item 32) from Scott Meyers "Effective STL” book.

vector<int> v; 
...
v.erase(remove(v.begin(), v.end(), 99), v.end());

remove basically returns the "new logical end” and elements of the original range that start at the "new logical end" of the range and continue until the real end of the range are the elements to be erased from container.

Sounds good. Now, let me ask my question:

In the above example, remove can return v.end() if 99 is not found in the vector v. It is basically passing past-the-end-iterator to erase method.

  1. What happens when past-the-end-iterator is passed to the erase method? Does standard says it a UB?
  2. If it is undefined behavior, then erase-remove idiom example in Scott Meyer’s book should have looked like:

  vector<int> v; 
    ...
    vector<int>::iterator newEndIter = remove(v.begin(), v.end(), 99);
    if(newEndIter != v.end() )
    {
     v.erase(newEndIter, v.end();
    }  

Any ideas on this?

aJ.
  • 34,624
  • 22
  • 86
  • 128
  • By definition v.end() is not `past-the-end`, it is the end :x – Matthieu M. Nov 05 '09 at 07:40
  • 4
    @Matthieu M. Documentation of std::vector::end() says: "Returns an iterator referring to the past-the-end element in the vector container." – Julien-L Nov 05 '09 at 09:53
  • @Julien-L: That's bad wording. The end iterator is one-past-the-last element. Does the C++ spec actually say that? That'd be surprising. – Mooing Duck Jul 13 '16 at 16:54
  • @MooingDuck Yes that's the wording used here: http://www.cplusplus.com/reference/vector/vector/end/ – Julien-L Jul 13 '16 at 19:16
  • 1
    @Julien-L: Not only is that site not the C++ spec, that site is notorious for misleading and even outright wrong information. However, the [C++14 draft spec](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf) (§ 23.2.1) does indeed state that "`end()` returns an iterator which is the past-the-end value for the container. " – Mooing Duck Jul 13 '16 at 20:47

3 Answers3

10

I would think v.erase(v.end(), v.end()) would be well defined and erase nothing.

Keith Randall
  • 22,985
  • 2
  • 35
  • 54
10

The C++ standard says that the erase(q1,q2) member "erases the elements in the range [q1,q2)" (cf. section 23.1.1). Since the range excludes the last element,

v.erase(v.end(), v.end());

is valid and erases nothing.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • You may need to explain what the mathematical notation [x,y) means. Unless you have a degree in maths (or related subject) you probably don't know. – Martin York Nov 05 '09 at 05:39
  • 2
    Really? I do have a degree in maths but I honestly always thought this notation was well-known. – rlbond Nov 05 '09 at 06:47
  • 1
    You can find the Wikipedia page on mathematical intervals at http://en.wikipedia.org/wiki/Interval_%28mathematics%29 – James McNellis Nov 05 '09 at 14:19
  • Thanks for the explanation, until now I was convinced `[a,a)` would include `a`, but somehow the exclusion of `)` is stronger then the inclusion of `[`. Interestingly, `(a,a)` is equal to `[a,a)` and `(a,a]`. – Antonio Jun 17 '22 at 14:54
2

C++ Reference claims:

The iterator first does not need to be dereferenceable if first==last: erasing an empty range is a no-op.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103