title: std::remove with vector::erase and undefined behavior
body: <p>All over the web I see people use the <a href="http://en.wikipedia.org/wiki/Erase-remove_idiom" rel="noreferrer">erase/remove idiom</a> for C++ vectors like so:</p>
  
  <pre><code>#include &lt;vector&gt; // the general-purpose vector container
  #include &lt;iostream&gt;
  #include &lt;algorithm&gt; // remove and remove_if
  int main()
  {
    // initialises a vector that holds the numbers from 0-9.
    std::vector&lt;int&gt; v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  
    // removes all elements with the value 5
    v.erase( std::remove( v.begin(), v.end(), 5 ), v.end() );
  
    return 0;
  }
  </code></pre>
  
  <p>That is, if I want to erase all elements matching some criteria (e.g. the number 5 from a vector of <code>int</code>s), then I use <code>std::remove</code> or <code>std::remove_if</code> in conjunction with <code>vector.erase</code> like so:</p>
  
  <pre><code>vector.erase( std::remove( vector.begin(), vector.end(), &lt;some_value&gt;), vector.end());
  </code></pre>
  
  <p>This works nicely in general; <code>std::remove</code> (and <code>remove_if</code>) will copy (or use move semantics in C++11) the elements that are to be deleted over to the end of the vector, so the vector from our previous example will now look like this:</p>
  
  <blockquote>
    <p>{ 0, 1, 2, 3, 4, 6, 7, 8, 9, <b>5</b> };</p>
  </blockquote>
  
  <p>With the element <strong>5</strong> bolded because it's been moved to the end.</p>
  
  <p>Now, <code>std::remove</code> will return an iterator to it, which we then use in <code>erase</code> to clear the elements out. Nice.</p>
  
  <h2>But what about the following example?</h2>
  
  <pre><code>int main()
  {
    // initialises an empty vector.
    std::vector&lt;int&gt; v = {};
  
    // removes all elements with the value 5
    v.erase( std::remove( v.begin(), v.end(), 5 ), v.end() );
  
    return 0;
  }
  </code></pre>
  
  <p>This seems to work as expected (not erasing anything, not segfaulting, etc.) on all platforms I run it on, but I know that just because something is working, doesn't mean it's not undefined behavior.</p>
  
  <p>The quick <a href="http://www.cplusplus.com/reference/vector/vector/erase/" rel="noreferrer">reference</a> for <code>vector.erase</code> says this (emphasis mine):</p>
  
  <pre><code>iterator erase (const_iterator first, const_iterator last);
  </code></pre>
  
  <p><code>first, last</code> are</p>
  
  <blockquote>
    <p>Iterators specifying a range within the vector] to be removed: <code>[first,last)</code>. i.e., the range includes all the elements between <code>first</code> and <code>last</code>, <strong>including the element pointed by first</strong> but not the one pointed by <code>last</code>.
     Member types <code>iterator</code> and <code>const_iterator</code> are random access iterator types that point to elements.</p>
  </blockquote>
  
  <h2>So is <code>vector.erase(vector.end(),vector.end())</code> undefined behavior?</h2>
  
  <p>Here's what the quick reference says about exception safety:</p>
  
  <blockquote>
    <p>If the removed elements include the last element in the container, no exceptions are thrown (no-throw guarantee).
     Otherwise, the container is guaranteed to end in a valid state (basic guarantee).
     An invalid <code>position</code> or <code>range</code> causes undefined behavior.</p>
  </blockquote>
  
  <p>So, the answer, at least to me appears to be "YES", and <a href="https://stackoverflow.com/a/9590202/27678">this StackOverflow answer</a> seems to support it.</p>
  
  <h2>Therefore, is the common idiom wrong?</h2>
  
  <p>Assuming it's undefined behavior, then any call to <code>remove</code> could return an iterator to <code>vector.end()</code> which should be checked before calling <code>vector.erase</code>, and calling remove on an empty vector does seem to return <code>vector.end</code>: (<a href="http://ideone.com/7sodQA" rel="noreferrer">IDEOne for code below</a>)</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;algorithm&gt;
  #include &lt;vector&gt;
  using namespace std;
  
  int main() {
     vector&lt;int&gt; myInts;
     auto anIter = std::remove(myInts.begin(),myInts.end(),5);
     if (anIter == myInts.end())
        std::cout &lt;&lt; "iterator = myInts.end()";
  }
  </code></pre>
  
  <h2>Finally, my question:</h2>
  
  <p>Should the actual remove/erase idiom be this?</p>
  
  <pre><code>auto endOfRangeIterator = std::remove(vector.begin(), vector.end(), &lt;value&gt;);
  if (endOfRangeIterator != vector.end())
     vector.erase(endOfRangeIterator, vector.end())
  </code></pre>