<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2160: Unintended destruction ordering-specification of resize</title>
<meta property="og:title" content="Issue 2160: Unintended destruction ordering-specification of resize">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2160.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++17">C++17</a> status.</em></p>
<h3 id="2160"><a href="lwg-defects.html#2160">2160</a>. Unintended destruction ordering-specification of <code>resize</code></h3>
<p><b>Section:</b> 23.3.13.3 <a href="https://wg21.link/vector.capacity">[vector.capacity]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2012-06-07 <b>Last modified:</b> 2017-07-30</p>
<p><b>Priority: </b>1
</p>
<p><b>View other</b> <a href="lwg-index-open.html#vector.capacity">active issues</a> in [vector.capacity].</p>
<p><b>View all other</b> <a href="lwg-index.html#vector.capacity">issues</a> in [vector.capacity].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>

<p>
As part of resolving LWG issue <a href="lwg-defects.html#2033" title="Preconditions of reserve, shrink_to_fit, and resize functions (Status: C++14)">2033</a><sup><a href="https://cplusplus.github.io/LWG/issue2033" title="Latest snapshot">(i)</a></sup> a wording change was done for <code>resize()</code> to 
respect the problem mentioned in the question:
</p>
<blockquote><p>
Does a call to 'void resize(size_type sz)' of <code>std::vector</code> require the element type to be 
<code>MoveAssignable</code> because the call <code>erase(begin() + sz, end())</code> mentioned in the Effects 
paragraph would require the element type to be <code>MoveAssignable</code>?
</p></blockquote>
<p>
The wording change was to replace in 23.3.5.3 <a href="https://wg21.link/deque.capacity">[deque.capacity]</a> and 23.3.13.3 <a href="https://wg21.link/vector.capacity">[vector.capacity]</a>:
</p>
<blockquote><p>
-1- <i>Effects</i>: If <code>sz &lt;= size()</code>, equivalent to <code>erase(begin() + sz, end())</code>; [&hellip;]
</p></blockquote>
<p>
by:
</p>
<blockquote><p>
-1- <i>Effects</i>: If <code>sz &lt;= size()</code>, equivalent to calling <code>pop_back() size() - sz</code> times. [&hellip;]
</p></blockquote>
<p>
The overlooked side-effect of this wording change is that this implies a destruction order
of the removed elements to be in reverse order of construction, but the previous version
did not impose any specific destruction order due to the way how the semantics of <code>erase</code>
is specified in Table 100.
<p/>
Given the program:
</p>
<blockquote><pre>
#include &lt;vector&gt;
#include &lt;iostream&gt;

struct Probe {
  int value;
  Probe() : value(0) {}
  Probe(int value) : value(value) {}
  ~Probe() { std::cout &lt;&lt; "~Probe() of " &lt;&lt; value &lt;&lt; std::endl; }
};

int main() {
  std::vector&lt;Probe&gt; v;
  v.push_back(Probe(1));
  v.push_back(Probe(2));
  v.push_back(Probe(3));
  std::cout &lt;&lt; "---" &lt;&lt; std::endl;
  <span style="color:#C80000;font-weight:bold">v.resize(0)</span>;
}
</pre></blockquote>
<p>
the last three lines of the output for every compiler I tested was:
</p>
<blockquote><pre>
~Probe() of 1
~Probe() of 2
~Probe() of 3
</pre></blockquote>
<p>
but a conforming implementation would now need to change this order to
</p>
<blockquote><pre>
~Probe() of 3
~Probe() of 2
~Probe() of 1
</pre></blockquote>
<p>
This possible stringent interpretation makes sense, because one can argue that sequence containers 
(or at least <code>std::vector</code>) should have the same required destruction order of it's elements,
as elements of a C array or controlled by memory deallocated with an array <code>delete</code> have.
I also learned that libc++ does indeed implement <code>std::vector::resize</code> in a way that the
second output form is observed.
<p/>
While I agree that required reverse-destruction would better mimic the natural behaviour of
<code>std::vector</code> this was not required in C++03 and this request may be too strong. My current 
suggestion would be to restore the effects of the previous wording <em>in regard to the destruction order</em>, 
because otherwise several currently existing implementations would be broken just because of this
additional requirement.
</p>

<p><i>[2013-03-15 Issues Teleconference]</i></p>

<p>
Moved to Open.
</p>
<p>
Jonathan says that he believes this is a valid issue.
</p>
<p>
Walter wonders if this was intended when we made the previous change - if so, this would be NAD.
</p>
<p>
Jonathan said that Issue <a href="lwg-defects.html#2033" title="Preconditions of reserve, shrink_to_fit, and resize functions (Status: C++14)">2033</a><sup><a href="https://cplusplus.github.io/LWG/issue2033" title="Latest snapshot">(i)</a></sup> doesn't mention ordering.
</p>
<p>
Walter then asked if anyone is really unhappy that we're destroying items in reverse order of construction.
</p>
<p>
Jonathan points out that this conflicts with existing practice (libstc++, but not libc++).
</p>
<p>
Jonathan asked for clarification as to whether this change was intended by <a href="lwg-defects.html#2033" title="Preconditions of reserve, shrink_to_fit, and resize functions (Status: C++14)">2033</a><sup><a href="https://cplusplus.github.io/LWG/issue2033" title="Latest snapshot">(i)</a></sup>.
</p>

<p><i>[2014-06 Rapperswil]</i></p>

<p>
Daniel points out that the ordering change was not intended.
<p/>
General agreement that implementations should not be required to change.
</p>

<p><i>[2014-06-28 Daniel provides alternative wording]</i></p>


<p><i>[Urbana 2014-11-07: Move to Ready]</i></p>




<p id="res-2160"><b>Proposed resolution:</b></p>
<p>This wording is relative to N3936.</p> 

<ol>
<li><p>Change 23.3.5.3 <a href="https://wg21.link/deque.capacity">[deque.capacity]</a> as indicated: [<i>Drafting note</i>: The chosen wording form is similar to that for
<code>forward_list</code>. Note that the existing <i>Requires</i> element already specifies the necessary operational requirements 
on the value type. &mdash; <i>end drafting note</i>]</p>

<blockquote>
<pre>
void resize(size_type sz);
</pre>
<blockquote>
<p>
-1- <i>Effects</i>: If <code>sz &lt;<del>=</del> size()</code>, <ins>erases the last <code>size() - sz</code> elements from the 
sequence</ins><del>equivalent to calling <code>pop_back() size() - sz</code> times</del>. <ins>Otherwise</ins><del>If <code>size() 
&lt;= sz</code></del>, appends <code>sz - size()</code> default-inserted elements to the sequence.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
void resize(size_type sz, const T&amp; c);
</pre>
<blockquote>
<p>
-3- <i>Effects</i>: If <code>sz &lt;<del>=</del> size()</code>, <ins>erases the last <code>size() - sz</code> elements from the 
sequence</ins><del>equivalent to calling <code>pop_back() size() - sz</code> times</del>. <ins>Otherwise</ins><del>If <code>size() 
&lt; sz</code></del>, appends <code>sz - size()</code> copies of <code>c</code> to the sequence.
<p/>
[&hellip;]
</p>
</blockquote>
</blockquote>
</li>

<li><p>Change 23.3.13.3 <a href="https://wg21.link/vector.capacity">[vector.capacity]</a> as indicated: [<i>Drafting note</i>: See <code>deque</code> for the rationale of the
used wording. &mdash; <i>end drafting note</i>]</p>

<blockquote>
<pre>
void resize(size_type sz);
</pre>
<blockquote>
<p>
-12- <i>Effects</i>: If <code>sz &lt;<del>=</del> size()</code>, <ins>erases the last <code>size() - sz</code> elements from the 
sequence</ins><del>equivalent to calling <code>pop_back() size() - sz</code> times</del>. <ins>Otherwise</ins><del>If <code>size() 
&lt; sz</code></del>, appends <code>sz - size()</code> default-inserted elements to the sequence.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
void resize(size_type sz, const T&amp; c);
</pre>
<blockquote>
<p>
-15- <i>Effects</i>: If <code>sz &lt;<del>=</del> size()</code>, <ins>erases the last <code>size() - sz</code> elements from the 
sequence</ins><del>equivalent to calling <code>pop_back() size() - sz</code> times</del>. <ins>Otherwise</ins><del>If <code>size() 
&lt; sz</code></del>, appends <code>sz - size()</code> copies of <code>c</code> to the sequence.
<p/>
[&hellip;]
</p>
</blockquote>
</blockquote>
</li>
</ol>






</body>
</html>
