<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 498: Requirements for partition() and stable_partition() too strong</title>
<meta property="og:title" content="Issue 498: Requirements for partition() and stable_partition() too strong">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue498.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++11">C++11</a> status.</em></p>
<h3 id="498"><a href="lwg-defects.html#498">498</a>. Requirements for partition() and stable_partition() too strong</h3>
<p><b>Section:</b> 26.8.5 <a href="https://wg21.link/alg.partitions">[alg.partitions]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> Sean Parent, Joe Gottman <b>Opened:</b> 2005-05-04 <b>Last modified:</b> 2025-03-13</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#alg.partitions">issues</a> in [alg.partitions].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++11">C++11</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Problem:
The iterator requirements for partition() and stable_partition() [25.2.12]
are listed as BidirectionalIterator, however, there are efficient algorithms
for these functions that only require ForwardIterator that have been known
since before the standard existed. The SGI implementation includes these (see
<a href="https://www.boost.org/sgi/stl/partition.html">https://www.boost.org/sgi/stl/partition.html</a>
and
<a href="https://www.boost.org/sgi/stl/stable_partition.html">https://www.boost.org/sgi/stl/stable_partition.html</a>).
</p>

<p><i>[
2009-04-30 Alisdair adds:
]</i></p>


<blockquote>
<p>
Now we have concepts this is easier to express!
</p>
<p>
Proposed resolution:
</p>
<p>
Add the following signature to:
</p>
<p>
Header <code>&lt;algorithm&gt;</code> synopsis  [algorithms.syn]<br/>
p3 Partitions 26.8.5 <a href="https://wg21.link/alg.partitions">[alg.partitions]</a>
</p>
<blockquote><pre>
 template&lt;ForwardIterator Iter, Predicate&lt;auto, Iter::value_type&gt; Pred&gt;
   requires ShuffleIterator&lt;Iter&gt;
         &amp;&amp; CopyConstructible&lt;Pred&gt;
   Iter partition(Iter first, Iter last, Pred pred);
</pre></blockquote>

<p>
Update p3 Partitions 26.8.5 <a href="https://wg21.link/alg.partitions">[alg.partitions]</a>:
</p>

<blockquote>
<p>
<i>Complexity:</i> <del>At most <code>(last - first)/2</code> swaps. Exactly <code>last - first</code>
applications of the predicate
are done.</del>
<ins>
If <code>Iter</code> satisfies <code>BidirectionalIterator</code>, at most <code>(last -
first)/2</code> swaps. Exactly <code>last - first</code> applications of the predicate
are done.
</ins>
</p>
<p><ins>
If <code>Iter</code> merely satisfied <code>ForwardIterator</code> at most <code>(last - first)</code> swaps
are done. Exactly <code>(last - first)</code> applications of the predicate are done.
</ins></p>
</blockquote>

<p>
[Editorial note: I looked for existing precedent in how we might call out
distinct overloads overloads from a set of constrained templates, but there
is not much existing practice to lean on.   advance/distance were the only
algorithms I could find, and that wording is no clearer.]
</p>

</blockquote>

<p><i>[
2009-07 Frankfurt
]</i></p>


<blockquote>
<p>
Hinnant: if you want to partition your std::forward_list, you'll need
partition() to accept ForwardIterators.
</p>
<p>
No objection to Ready.
</p>
<p>
Move to Ready.
</p>
</blockquote>



<p id="res-498"><b>Proposed resolution:</b></p>
<p>
Change 25.2.12 from </p>
<blockquote><pre>
template&lt;class BidirectionalIterator, class Predicate&gt; 
BidirectionalIterator partition(BidirectionalIterato r first, 
                                BidirectionalIterator last, 
                                Predicate pred); 
</pre></blockquote>
<p>to </p>
<blockquote><pre>
template&lt;class ForwardIterator, class Predicate&gt; 
ForwardIterator partition(ForwardIterator first, 
                          ForwardIterator last, 
                          Predicate pred); 
</pre></blockquote>
<p>Change the complexity from </p>

<blockquote><p>
At most (last - first)/2 swaps are done. Exactly (last - first) 
applications of the predicate are done. 
</p></blockquote>

<p>to </p>

<blockquote><p>
If ForwardIterator is a bidirectional_iterator, at most (last - first)/2 
swaps are done; otherwise at most (last - first) swaps are done. Exactly 
(last - first) applications of the predicate are done. 
</p></blockquote>



<p><b>Rationale:</b></p>
<p>
Partition is a "foundation" algorithm useful in many contexts (like sorting
as just one example) - my motivation for extending it to include forward
iterators is foward_list - without this extension you can't partition an foward_list
(without writing your own partition). Holes like this in the standard
library weaken the argument for generic programming (ideally I'd be able
to provide a library that would refine std::partition() to other concepts
without fear of conflicting with other libraries doing the same - but
that is a digression). I consider the fact that partition isn't defined
to work for ForwardIterator a minor embarrassment.
</p>

<p><i>[Mont Tremblant:  Moved to Open, request motivation and use cases by next meeting. Sean provided further rationale by post-meeting mailing.]</i></p>







</body>
</html>
