<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1251: move constructing basic_stringbuf</title>
<meta property="og:title" content="Issue 1251: move constructing basic_stringbuf">
<meta property="og:description" content="C++ library issue. Status: NAD">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1251.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="1251"><a href="lwg-closed.html#1251">1251</a>. move constructing <code>basic_stringbuf</code></h3>
<p><b>Section:</b> 31.8.2.2 <a href="https://wg21.link/stringbuf.cons">[stringbuf.cons]</a> <b>Status:</b> <a href="lwg-active.html#NAD">NAD</a>
 <b>Submitter:</b> Martin Sebor <b>Opened:</b> 2009-10-29 <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#stringbuf.cons">issues</a> in [stringbuf.cons].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD">NAD</a> status.</p>
<p><b>Discussion:</b></p>
<p>
I just came across issue <a href="lwg-defects.html#1204" title="Global permission to move (Status: C++11)">1204</a><sup><a href="https://cplusplus.github.io/LWG/issue1204" title="Latest snapshot">(i)</a></sup> -- Global permission to move, which
seems to address the concern raised by the example in c++std-lib-25030.
</p>
<p>
IIUC, the example violates the permission to assume that arguments
bound to rvalue references are unnamed temporaries granted to
implementations by the resolution of issue <a href="lwg-defects.html#1204" title="Global permission to move (Status: C++11)">1204</a><sup><a href="https://cplusplus.github.io/LWG/issue1204" title="Latest snapshot">(i)</a></sup> - Global permission
to move.
</p>

<p>
I.e., the <code>ostringstream(ostringstream &amp;&amp;rhs)</code> ctor can leave the <code>rhs</code>
pointers pointing to the newly constructed object's buffer just as
long as the dtor doesn't change or invalidate the buffer. The caller
may not make any assumptions about rhs after the move beyond it being
safe to destroy or reassign.
</p>

<p>
So unless I misunderstood something, I still think the <code>basic_stringbuf</code>
move ctor is overspecified. Specifically, I think the third sentence
in the Effects clause and the last 6 bullets in the Postconditions
clause can, and IMO should, be stricken.
</p>

<p><i>[
2010-01-31 Moved to Tentatively NAD after 5 positive votes on c++std-lib.
Rationale added below.
]</i></p>



<p><b>Rationale:</b></p>
<p>
The sense of 1251 appears to be that the <code>basic_stringbuf</code> move
constructor offers more guarantees than the minimum.  This is true, and quite
correct.  The additional words guarantee that the internal buffer has genuinely
transferred from one object to another, and further operations on the original
will not affect the buffer of the newly created object.  This is a very
important guarantee, much as we see that a moved-from <code>unique_ptr</code> is
guaranteed to be empty.
</p>


<p id="res-1251"><b>Proposed resolution:</b></p>
<p>
Strike from 31.8.2.2 <a href="https://wg21.link/stringbuf.cons">[stringbuf.cons]</a>:
</p>

<blockquote><pre>
basic_stringbuf(basic_stringbuf&amp;&amp; rhs);
</pre>
<blockquote>
<p>
<i>Effects:</i> Move constructs from the rvalue <code>rhs</code>. It is
implementation-defined whether the sequence pointers in <code>*this</code>
(<code>eback()</code>, <code>gptr()</code>, <code>egptr()</code>, <code>pbase()</code>,
<code>pptr()</code>, <code>epptr()</code>) obtain the values which <code>rhs</code>
had. <del>Whether they do or not, <code>*this</code> and <code>rhs</code> reference
separate buffers (if any at all) after the construction.</del> The openmode,
locale and any other state of <code>rhs</code> is also copied.
</p>

<p>
<i>Postconditions:</i> Let <code>rhs_p</code> refer to the state of
<code>rhs</code> just prior to this construction and let <code>rhs_a</code>
referto the state of <code>rhs</code> just after this construction.
</p>
<ul>
<li>
<code>str() == rhs_p.str()</code>
</li>
<li>
<code>gptr() - eback() == rhs_p.gptr() - rhs_p.eback()</code>
</li>
<li>
<code>egptr() - eback() == rhs_p.egptr() - rhs_p.eback()</code>
</li>
<li>
<code>pptr() - pbase() == rhs_p.pptr() - rhs_p.pbase()</code>
</li>
<li>
<code>epptr() - pbase() == rhs_p.epptr() - rhs_p.pbase()</code>
</li>
<li><del>
if <code>(eback()) eback() != rhs_a.eback()</code>
</del></li>
<li><del>
if <code>(gptr()) gptr() != rhs_a.gptr()</code>
</del></li>
<li><del>
if <code>(egptr()) egptr() != rhs_a.egptr()</code>
</del></li>
<li><del>
if <code>(pbase()) pbase() != rhs_a.pbase()</code>
</del></li>
<li><del>
if <code>(pptr()) pptr() != rhs_a.pptr()</code>
</del></li>
<li><del>
if <code>(epptr()) epptr() != rhs_a.epptr()</code>
</del></li>
</ul>
</blockquote>
</blockquote>






</body>
</html>
