<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 855: capacity() and reserve() for deque?</title>
<meta property="og:title" content="Issue 855: capacity() and reserve() for deque?">
<meta property="og:description" content="C++ library issue. Status: NAD">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue855.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#NAD">NAD</a> status.</em></p>
<h3 id="855"><a href="lwg-closed.html#855">855</a>. capacity() and reserve() for deque?</h3>
<p><b>Section:</b> 23.3.5.3 <a href="https://wg21.link/deque.capacity">[deque.capacity]</a> <b>Status:</b> <a href="lwg-active.html#NAD">NAD</a>
 <b>Submitter:</b> Herv&eacute; Br&ouml;nnimann <b>Opened:</b> 2008-06-11 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#deque.capacity">issues</a> in [deque.capacity].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD">NAD</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The main point is that <code>capacity</code> can be viewed as a mechanism to  
guarantee the validity of <code>iterators</code> when only <code>push_back/pop_back</code>
operations are used.  For <code>vector</code>, this goes with reallocation.  For  
<code>deque</code>, this is a bit more subtle:  <code>capacity()</code> of a <code>deque</code> may shrink,  
whereas that of <code>vector</code> doesn't.   In a circular buffer impl. of the  
map, as Howard did, there is very similar notion of capacity: as long  
as <code>size()</code> is less than <code>B * (</code>total size of the map <code>- 2)</code>, it is  
guaranteed that no <code>iterator</code> is invalidated after any number of  
<code>push_front/back</code> and <code>pop_front/back</code> operations.  But this does not  
hold for other implementations.
</p>
<p>
Still, I believe, <code>capacity()</code> can be defined by <code>size() +</code>  how many  
<code>push_front/back</code> minus <code>pop_front/back</code> that can be performed before  
terators are invalidated.  In a classical impl., <code>capacity() = size()
+ </code> the min distance to either "physical" end of the deque (i.e.,  
counting the empty space in the last block plus all the blocks until  
the end of the map of block pointers).  In Howard's circular buffer  
impl., <code>capacity() = B * (</code>total size of the map <code>- 2)</code> still works with  
this definition, even though the guarantee could be made stronger.
</p>
<p>
A simple picture of a deque:
</p>
<blockquote><pre>
A-----|----|-----|---F+|++++|++B--|-----|-----Z
</pre></blockquote>
<p>
(A,Z mark the beginning/end, | the block boundaries, F=front, B=back,  
and - are uninitialized, + are initialized)
In that picture:  <code>capacity = size() + min(dist(A,F),dist(B,Z)) = min 
(dist(A,B),dist(F,Z))</code>.
</p>
<p>
<code>Reserve(n)</code> can grow the map of pointers and add possibly a number of  
empty blocks to it, in order to guarantee that the next <code>n-size()
push_back/push_front</code> operations will not invalidate iterators, and  
also will not allocate (i.e. cannot throw).  The second guarantee is  
not essential and can be left as a QoI.  I know well enough existing  
implementations of <code>deque</code> (sgi/stl, roguewave, stlport, and  
dinkumware) to know that either can be implemented with no change to  
the existing class layout and code, and only a few modifications if  
blocks are pre-allocated (instead of always allocating a new block,  
check if the next entry in the map of block pointers is not zero).
</p>
<p>
Due to the difference with <code>vector</code>, wording is crucial.  Here's a  
proposed wording to make things concrete;  I tried to be reasonably  
careful but please double-check me:
</p>

<p><i>[
San Francisco:
]</i></p>


<blockquote>
<p>
Hans: should the Returns clause for capacity read "1 Returns: A lower
bound..." rather than "1 Returns: An upper bound..."
</p>
<p>
Howard: maybe what's needed is capacity_front and capacity_back. In
fact, I think I implemented a deque that had these members as
implementation details.
</p>
</blockquote>



<p id="res-855"><b>Proposed resolution:</b></p>

<p>
Add new signatures to synopsis in 23.3.5 <a href="https://wg21.link/deque">[deque]</a>:
</p>

<blockquote><pre>
size_type capacity() const;
bool reserve(size_type n);
</pre></blockquote>

<p>
Add new signatures to 23.3.5.3 <a href="https://wg21.link/deque.capacity">[deque.capacity]</a>:
</p>

<blockquote>
<pre>
size_type capacity() const;
</pre>
<blockquote>
<p>
1 <i>Returns:</i> An upper bound on <code>n + max(n_f - m_f, n_b - m_b)</code>  such  
that, for any sequence of <code>n_f push_front</code>, <code>m_f pop_front</code>, <code>n_b  
push_back</code>, and <code>m_b pop_back</code> operations, interleaved in any order,  
starting with the current <code>deque</code> of size <code>n</code>, the <code>deque</code> does not  
invalidate any of its iterators except to the erased elements.
</p>
<p>
2 <i>Remarks:</i>  Unlike a <code>vector</code>'s capacity, the capacity of a <code>deque</code> can  
decrease after a sequence of insertions at both ends, even if none of  
the operations caused the <code>deque</code> to invalidate any of its iterators  
except to the erased elements.
</p>
</blockquote>
</blockquote>

<blockquote>
<pre>
bool reserve(size_type n);
</pre>
<blockquote>
<p>
2 <i>Effects:</i> A directive that informs a <code>deque</code> of a planned sequence of  
<code>push_front</code>, <code>pop_front</code>, <code>push_back</code>, and <code>pop_back</code> operations, so that it  
can manage iterator invalidation accordingly. After <code>reserve()</code>,  
<code>capacity()</code> is greater or equal to the argument of <code>reserve</code> if this  
operation returns <code>true</code>; and equal to the previous value of <code>capacity()</code>
otherwise.  If an exception is thrown, there are no effects.
</p>
<p>
3 <i>Returns:</i> <code>true</code> if iterators are invalidated as a result of this  
operation, and false otherwise.
</p>
<p>
4 <i>Complexity:</i> It does not change the size of the sequence and takes  
at most linear time in <code>n</code>.
</p>
<p>
5 <i>Throws:</i> <code>length_error</code> if <code>n &gt; max_size()</code>.
</p>
<p>
6 <i>Remarks:</i> It is guaranteed that no invalidation takes place during a  
sequence of <code>insert</code> or <code>erase</code> operations at either end that happens  
after a call to <code>reserve()</code> except to the erased elements, until the  
time when an insertion would make <code>max(n_f-m_f, n_b-m_b)</code> larger than  
<code>capacity()</code>, where <code>n_f</code> is the number of <code>push_front</code>, <code>m_f</code> of <code>pop_front</code>,  
<code>n_b</code> of <code>push_back</code>, and <code>m_b</code> of <code>pop_back</code> operations since the call to  
<code>reserve()</code>.
</p>
<p>
7        An implementation is free to pre-allocate buffers so as to  
offer the additional guarantee that no exception will be thrown  
during such a sequence other than by the element constructors.
</p>
</blockquote>
</blockquote>

<p>
And 23.3.5.4 <a href="https://wg21.link/deque.modifiers">[deque.modifiers]</a> para 1, can be enhanced:
</p>

<blockquote><p>
1 <i>Effects:</i> An insertion in the middle of the deque invalidates all the iterators and references to elements of the
deque. An insertion at either end of the deque invalidates all the iterators to the deque,
<ins>unless provisions have been made with reserve,</ins>
but has no effect on the validity of references to elements of the deque.
</p></blockquote>


<p><b>Rationale:</b></p>
<p>Complication outweighs the benefit.</p>





</body>
</html>
