<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style type="text/css">
.comment { color: #999999; font-style: italic; }
.pre { color: #000099; }
.string { color: #009900; }
.char { color: #009900; }
.float { color: #996600; }
.int { color: #999900; }
.bool { color: #000000; font-weight: bold; }
.type { color: #FF6633; }
.flow { color: #FF0000; }
.keyword { color: #990000; }
.operator { color: #663300; font-weight: bold; }
.operator { color: #663300; font-weight: bold; }
pre.code {
    border: 2px solid #666;
    background-color: #F4F4F4;
    padding-left: 10px;
    padding-top: 0px;
}
code {
    border: 2px solid #d0d0d0;
    background-color: LightYellow;
    padding: 2px;
    padding-left: 10px;
    display:table;
    white-space:pre;
    margin:2px;
    margin-bottom:10px;
}
dt
{
    font-weight: bold;
}
    
.ins {
    background-color:#A0FFA0;
}

.del {
    background-color:#FFA0A0;
    text-decoration:line-through
}    
</style>    <title>Making non-modifying sequence operations more robust: Revision 2</title></head><body>
<p>N3671<br>
Revision of: N3607<br>
    2013-04-19<br>
    Mike Spertus, Symantec<br>
    <a href="mailto:mike_spertus@symantec.com"><tt>mike_spertus@symantec.com</tt></a><br>
    Attila Pall, Symantec<br>
    <a href="mailto:Attila_Pall@symantec.com"><tt>Attila_Pall@symantec.com</tt></a><br></p>
<h1>Making non-modifying sequence operations more robust: Revision 2</h1>
<h2>Overview</h2>
<p>We propose adding overloads for <tt>std::equal</tt>, <tt>std::mismatch</tt>, and <tt>std::is_permutation</tt>
to accept two ranges. When using
these overloads, the caller does not need to separately
check that the two ranges are of the same length.</p> 

<p>We illustrate this using <tt>std::equal</tt>. For example:
<code>vector&lt;int&gt; v1 = { 1, 4 9 };
vector&lt;int&gt; v2 = { 1, 4, 9, 16, 25, 36, 49 };
vector&lt;int&gt; v3 = { 1, 2, 3, 4 };
assert(!equal(v1.begin(), v1.end(), v2.begin(), v2.end());</code></p>

<p>These overloads provide three benefits.</p>
<ul>
<li>Since one almost always needs to check that the two sequences are of the
same length, having a single function that comprehensively checks sequences
for equality is clearer and less brittle.</li>
<li><p>If one neglects to check that the two ranges are the same length, the 
existing forms of <tt>equal</tt> will appear to function correctly most of the time,
even on sequences of different length. For example, in the following snippets,
assume the programmer intended to compare the entire vectors:
<code>equal(v1.begin(), v1.end(), v3.begin()); <span class="comment">// Gives desired answer by luck</span></code>
but of course occasionally give an incorrect answer
<code>equal(v1.begin(), v1.end(), v2.begin()); <span class="comment">// Oops! Returns true for unequal sequences</span></code>  
or even crash <code>equal(v2.begin(), v2.end(), v1.begin()) <span class="comment">// Oops! Undefined behavior</span></code>
would exhibit undefined behavior above), the majority of the time, it will appear
to function correctly.</p>
<p>As a result, programs are likely to pass systems testing and QA but intermittently
exhibit incorrect errors in deployment. At our company, code that had run apparently
correctly for years, started crashing our cloud servers as a result of this error.
The impact and cost to fix this problem was obviously far higher than if <tt>equal</tt>
checked for full equality of sequences (including length)</p></li>
<li>If the sequences do not satisfy the requirements of a random iterator
(§24.2.7 [random.access.iterator]), then checking that the sequences are
of the same length is much more efficient to do while comparing elements for equality.</li></ul>
<p>Note that if random access iterators are passed to the new overloads
of equal <tt>equal</tt> or <tt>is_permutation</tt>,
they will compare the length of sequences
up front to quickly reject unequal length sequences.
Even though they don't fully replace the existing overloads, we feel having 
overloads that properly handle sequences that are not
known to be of the same length are well worth having.</p>
<p>While we focused on the case of <tt>equal</tt> in the text above, the same
considerations apply to <tt>is_permutation</tt>, and <tt>mismatch</tt>, which
are the other non-modifying sequence operators that work on pairs of iterators
but do not allow passing the end to the second range, so we include them in our proposal
as well.</p>
<h2>Wording</h2>
In the synopsis of §25.1 [algorithms.general], make the following changes:
<blockquote>
<pre style="padding:0;margin:0">template&lt;class InputIterator, class Predicate&gt;
  typename iterator_traits&lt;InputIterator&gt;::difference_type
    count_if(InputIterator first, InputIterator last, Predicate pred);
		
template&lt;class InputIterator1, class InputIterator2&gt;
  pair&lt;InputIterator1, InputIterator2&gt;
    mismatch(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2);
						 
template
 &lt;class InputIterator1, class InputIterator2, class BinaryPredicate&gt;
  pair&lt;InputIterator1, InputIterator2&gt;
    mismatch(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, BinaryPredicate pred);

<span class="ins">template&lt;class InputIterator1, class InputIterator2&gt;
  pair&lt;InputIterator1, InputIterator2&gt;
    mismatch(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, InputIterator2 last2);
						 
template
 &lt;class InputIterator1, class InputIterator2, class BinaryPredicate&gt;
  pair&lt;InputIterator1, InputIterator2&gt;
    mismatch(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, InputIterator2 last2,
             BinaryPredicate pred);

</span>template&lt;class InputIterator1, class InputIterator2&gt;
  bool equal(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2);

template
 &lt;class InputIterator1, class InputIterator2, class BinaryPredicate&gt;
  bool equal(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, BinaryPredicate pred);

<span class="ins">template&lt;class InputIterator1, class InputIterator2&gt;
  bool equal(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, InputIterator2 last2);

template
 &lt;class InputIterator1, class InputIterator2, class BinaryPredicate&gt;
  bool equal(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, InputIterator2 last2,
             BinaryPredicate pred);

</span>template&lt;class ForwardIterator1, class ForwardIterator2&gt;
  bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1,
                      ForwardIterator2 first2);
											
template&lt;class ForwardIterator1, class ForwardIterator2,
                    class BinaryPredicate&gt;
  bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1,
                      ForwardIterator2 first2, BinaryPredicate pred);

<span class="ins">template&lt;class ForwardIterator1, class ForwardIterator2&gt;
  bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1,
                      ForwardIterator2 first2, ForwardIterator2 last2);

template&lt;class ForwardIterator1, class ForwardIterator2,
                    class BinaryPredicate&gt;
  bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1,
                      ForwardIterator2 first2, ForwardIterator2 last2,
                      BinaryPredicate pred);

</span>template&lt;class ForwardIterator1, class ForwardIterator2&gt;
  ForwardIterator1 search(
    ForwardIterator1 first1, ForwardIterator1 last1,
    ForwardIterator2 first2, ForwardIterator2 last2);</pre></blockquote>
<p>Modify §25.2.10 [mismatch] as follows</p>
<blockquote><pre style="padding:0;margin:0">template&lt;class InputIterator1, class InputIterator2&gt;
  pair&lt;InputIterator1, InputIterator2&gt;
    mismatch(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2);
						 
template
 &lt;class InputIterator1, class InputIterator2, class BinaryPredicate&gt;
  pair&lt;InputIterator1, InputIterator2&gt;
    mismatch(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, BinaryPredicate pred);

<span class="ins">template&lt;class InputIterator1, class InputIterator2&gt;
  pair&lt;InputIterator1, InputIterator2&gt;
    mismatch(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, InputIterator2 last2);
						 
template
 &lt;class InputIterator1, class InputIterator2, class BinaryPredicate&gt;
  pair&lt;InputIterator1, InputIterator2&gt;
    mismatch(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, InputIterator2 last2,
             BinaryPredicate pred);</span></pre>
<br>
<span class="ins"><em>Remarks:</em> If <tt>last2</tt> was not given in the
argument list, it denotes <tt>first2 + (last1 - first1)</tt> below.</span><br><br>
<em>Returns: </em> A pair of iterators <tt>i</tt> and <tt>j</tt> such that  
<tt>j == first2 + (i - first1)</tt> and <tt>i</tt> is the first iterator
in the range <tt>[first1,last1)</tt> for which the following corresponding conditions hold:<br>
<blockquote><span class="ins"><tt>j</tt> is in the range <tt>[first2, last2)</tt>.</span><br><pre style="padding:0;margin:0">!(*i == *(first2 + (i - first1)))
pred(*i, *(first2 + (i - first1))) == false</pre></blockquote>
Returns the pair <span class="del"><tt>last1</tt></span>
<span class="ins"><tt>first1 + min(last1 - first1, last2 - first2)</tt></span> and 
<span class="del"><tt>first2 + (last1 - first1)</tt></span>
<span class="ins"><tt>first2 + min(last1 - first1, last2 - first2)</tt></span>
if such an iterator <tt>i</tt> is not found.</blockquote>
<p>Modify §25.2.10 [alg.equal] as follows:</p>
<blockquote><pre style="padding:0;margin:0">template&lt;class InputIterator1, class InputIterator2&gt;
  bool equal(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2);

template
 &lt;class InputIterator1, class InputIterator2, class BinaryPredicate&gt;
  bool equal(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, BinaryPredicate pred);

<span class="ins">template&lt;class InputIterator1, class InputIterator2&gt;
  bool equal(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, InputIterator2 last2);

template&lt;class InputIterator1, class InputIterator2,
           class BinaryPredicate&gt;
  bool equal(InputIterator1 first1, InputIterator1 last1,
             InputIterator2 first2, InputIterator2 last2,
             BinaryPredicate pred);</span></pre>
<br>
<span class="ins"><em>Remarks:</em> If <tt>last2</tt> was not given in the
argument list, it denotes <tt>first2 + (last1 - first1)</tt> below.</span><br><br>
<em>Returns:</em> <span class="ins">If <tt>last1 - first1 != last2 - first2</tt>,
return <tt>false</tt>. Otherwise return </span> <tt>true</tt> if
for every iterator <tt>i</tt> in the range <tt>[first1,last1)</tt>
the following corresponding conditions
hold: <tt>*i == *(first2 + (i - first1))</tt>, <tt>pred(*i, *(first2 + (i - first1))) != false</tt>.
Otherwise, returns false.<br>
<br>
<em>Complexity:</em> <span class="ins">No applications of the 
corresponding predicate if <tt>InputIterator1</tt> and <tt>InputIterator2</tt> meet the
requirements of random access iterators and <tt>last1 - first1 != last2 - first2</tt>.
Otherwise, </span>
<span class="del">A</span><span class="ins">a</span>t most <span class="del"><tt>last1 - first1</tt></span>
<span class="ins"><tt>min(last1 - first1, last2 - first2)</tt></span>
 applications of the corresponding predicate.</blockquote>
Modify §25.2.12 [alg.is_permutation] as follows:
<blockquote><pre style="padding:0;margin:0">template&lt;class ForwardIterator1, class ForwardIterator2&gt;
  bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1,
                      ForwardIterator2 first2);
template&lt;class ForwardIterator1, class ForwardIterator2,
                 class BinaryPredicate&gt;
  bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1,
                      ForwardIterator2 first2, BinaryPredicate pred);
<span class="ins">template&lt;class ForwardIterator1, class ForwardIterator2&gt;
  bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1,
                      ForwardIterator2 first2, ForwardIterator2 last2);
template&lt;class ForwardIterator1, class ForwardIterator2,
                 class BinaryPredicate&gt;
  bool is_permutation(ForwardIterator1 first1, ForwardIterator1 last1,
                      ForwardIterator2 first2, ForwardIterator2 last2,
                      BinaryPredicate pred);</span></pre>
<br>
<em>Requires:</em> <tt>ForwardIterator1</tt> and <tt>ForwardIterator2</tt>
shall have the same value type. The comparison function shall be an equivalence
relation.<br>
<br>
<span class="ins"><em>Remarks:</em> If <tt>last2</tt> was not given in the
argument list, it denotes <tt>first2 + (last1 - first1)</tt> below.</span><br><br>
<em>Returns:</em> <span class="ins">If <tt>last1 - first1 != last2 - first2</tt>,
return <tt>false</tt>. Otherwise return </span>
<tt>true</tt> if there exists a permutation of the elements in the range <tt>[first2,first2 + (last1
- first1))</tt>, beginning with <tt>ForwardIterator2 begin</tt>, such that <tt>equal(first1, last1, begin)</tt>
returns <tt>true</tt> or <tt>equal(first1, last1, begin, pred)</tt> returns <tt>true</tt>; otherwise, returns <tt>false</tt>.<br>
<br>
<em>Complexity:</em> <span class="ins">No applications of the 
corresponding predicate if <tt>ForwardIterator1</tt> and <tt>ForwardIterator2</tt> meet the
requirements of random access iterators and <tt>last1 - first1 != last2 - first2</tt>.</span>
<span class=ins>Otherwise, e</span><span class="del">E</span>xactly <tt>last1 - first1</tt> applications of the corresponding 
predicate if <tt>equal(first1, last1, first2<span class="ins">, last2</span>)</tt> would return <tt>true</tt>
<span class="ins">if <tt>pred</tt> was not given in the argument list</span> or 
<tt>equal(first1, last1, first2, <span class="ins">last2</span>, pred)</tt> would return <tt>true</tt>
<span class="ins">if <tt>pred</tt> was given in the argument list</span>; 
otherwise, at worst <var>O(N<sup>2</sup>)</var>, where <var>N</var> has the value <tt>last1 - first1</tt>.
</blockquote>



</body></html>