<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1448: Concerns about basic_stringbuf::str(basic_string) postconditions</title>
<meta property="og:title" content="Issue 1448: Concerns about basic_stringbuf::str(basic_string) postconditions">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1448.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="1448"><a href="lwg-defects.html#1448">1448</a>. Concerns about <code>basic_stringbuf::str(basic_string)</code> postconditions</h3>
<p><b>Section:</b> 31.8.2.4 <a href="https://wg21.link/stringbuf.members">[stringbuf.members]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> BSI <b>Opened:</b> 2010-08-25 <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.members">issues</a> in [stringbuf.members].</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><b>Addresses GB-124</b></p>

<p>
N3092 31.8.2.4 <a href="https://wg21.link/stringbuf.members">[stringbuf.members]</a> contains this text specifying the postconditions of
<code>basic_stringbuf::str(basic_string)</code>:
</p>
<blockquote><p>
Postconditions: If <code>mode &amp; ios_base::out</code> is <code>true</code>,
<code>pbase()</code> points to the first underlying character and <code>epptr() >=
pbase() + s.size()</code> holds; in addition, if <code>mode &amp; ios_base::in</code>
is <code>true</code>, <code>pptr() == pbase() + s.data()</code> holds, otherwise
<code>pptr() == pbase()</code> is <code>true</code>. [...]
</p></blockquote>
<p>
Firstly, there's a simple mistake: It should be <code>pbase() + s.length()</code>,
not <code>pbase() + s.data()</code>.
</p>
<p>
Secondly, it doesn't match existing implementations. As far as I can tell,
GCC 4.5 does not test for <code>mode &amp; ios_base::in</code> in the second part
of that sentence, but for <code>mode &amp; (ios_base::app | ios_base_ate)</code>,
and Visual C++ 9 for <code>mode &amp; ios_base::app</code>. Besides, the wording of
the C++0x draft doesn't make any sense to me. I suggest changing the second part
of the sentence to one of the following:
</p>
<p>
Replace <code>ios_base::in</code> with <code>(ios_base::ate | ios_base::app)</code>,
but this would require Visual C++ to change (replacing only with
<code>ios_base::ate</code> would require GCC to change, and would make
<code>ios_base::app</code> completely useless with <code>stringstreams</code>):
</p>
<p>
in addition, if <code>mode &amp; (ios_base::ate | ios_base::app)</code> is <code>true</code>,
<code>pptr() == pbase() + s.length()</code> holds, otherwise <code>pptr() == pbase()</code>
is <code>true</code>.
</p>
<p>
Leave <code>pptr()</code> unspecified if <code>mode &amp; ios_base::app</code>, but not
<code>mode &amp; ios_base::ate</code> (implementations already differ in this case, and it
is always possible to use <code>ios_base::ate</code> to get the effect of appending, so it
is not necessary to require any implementation to change):
</p>
<p>
in addition, if <code>mode &amp; ios_base::ate</code> is <code>true</code>,
<code>pptr() == pbase() + s.length()</code> holds, if neither <code>mode &amp; ios_base::ate</code>
nor <code>mode &amp; ios_base::app</code> is <code>true</code>, <code>pptr() == pbase()</code> holds,
otherwise <code>pptr() >= pbase() &amp;&amp; pptr() &lt;= pbase() + s.length()</code>
(which of the values in this range is unspecified).
</p>
<p>
Slightly stricter:
</p>
<p>
in addition, if <code>mode &amp; ios_base::ate</code> is <code>true</code>,
<code>pptr() == pbase() + s.length()</code> holds, if neither
<code>mode &amp; ios_base::ate</code> nor <code>mode &amp; ios_base::app</code> is <code>true</code>,
<code>pptr() == pbase()</code> holds, otherwise <code>pptr() == pbase() || pptr() == pbase() + s.length()</code>
(which of these two values is unspecified). A small table might help to better explain the three cases.
BTW, at the end of the postconditions is this text: &quot;<code>egptr() == eback() + s.size()</code> hold&quot;.
Is there a perference for <code>basic_string::length</code> or <code>basic_string::size</code>? It doesn't really
matter, but it looks a bit inconsistent.
</p>

<p><i>[2011-03-09: Nicolai Josuttis comments and drafts wording]</i></p>


<p>First, it seems the current wording is just an editorial mistake.
When we added issue <a href="lwg-defects.html#432" title="stringbuf::overflow() makes only one write position available (Status: CD1)">432</a><sup><a href="https://cplusplus.github.io/LWG/issue432" title="Latest snapshot">(i)</a></sup>
to the draft standard (in <a href="http://www.open-std.org/jtc1/sc22/wg21/prot/14882fdis/n1733.pdf">n1733</a>), 
the wording in the issue:
</p>

<blockquote><p>
If <code>mode &amp; ios_base::out</code> is true, initializes the output sequence
such that <code>pbase()</code> points to the first underlying character, <code>epptr()</code> 
points one past the last underlying character, and if <code>(mode &amp; ios_base::ate)</code> is true,
<code>pptr()</code> is set equal to <code>epptr()</code> else <code>pptr()</code> is set equal to 
<code>pbase()</code>.
</p></blockquote>

<p>became:</p>

<blockquote><p>
If <code>mode &amp; ios_base::out</code> is true, initializes the output sequence
such that <code>pbase()</code> points to the first underlying character, <code>epptr()</code> 
points one past the last underlying character, and <code>pptr()</code> is equal to <code>epptr()</code>
if <code>mode &amp; ios_base::in</code> is true, otherwise <code>pptr()</code> is equal to 
<code>pbase()</code>.
</p></blockquote>

<p>
which beside some changes of the order of words changed
</p>
<blockquote><pre>
ios_base::ate
</pre></blockquote>
<p>
into
</p>
<blockquote><pre>
ios_base::in
</pre></blockquote>
<p>
So, from this point of view, clearly <code>mode &amp; ios_base::ate</code> was meant.
</p>

<p>
Nevertheless, with this proposed resolution we'd have no wording regarding <code>ios_base::app</code>.
Currently the only statements about <code>app</code> in the Standard are just in two tables:
</p>
<ul>
<li>Table 125 &mdash; &quot;<code>openmode</code> effects&quot; says that the effect of 
<code>app</code> is "seek to end before each write"
</li>

<li>Table 132 &mdash; &quot;File open modes&quot; says that the stdio equivalent 
for <code>app</code> is <code>"a"</code>
</li>
</ul>
<p>
Indeed we seem to have different behavior currently in respect to <code>app</code>: For
</p>

<blockquote><pre>
stringstream s2(ios_base::out|ios_base::in|ios_base::app);
s2.str("s2 hello");
s1 &lt;&lt; "more";
</pre></blockquote>

<ul>
<li>Visual C++ 10 does overwrite (=> <code>"moreello"</code>)</li>
<li>G++ 4.5 does append (=> <code>"s2 hellomore"</code>)</li>
</ul>

<p>BTW, for fstreams, both implementations append when <code>app</code> is set:
If <code>f2.txt</code> has contents <code>"xy"</code>,</p>

<blockquote><pre>
fstream f2("f2.txt",ios_base::out|ios_base::in|ios_base::app);
f1 &lt;&lt; "more";
</pre></blockquote>

<p>appends <code>"more"</code> so that the contents is <code>"xymore"</code>.</p>

<p>So IMO <code>app</code> should set the write pointer to the end so that each writing 
appends.
<p/>
I don't know whether what the standard says is enough. You can argue the 
statement in Table 125 clearly states that such a buffer should always append, 
which of course also applies to <code>str()</code> of stringbuffer.
<p/>
Nevertheless, it doesn't hurt IMO if we clarify the behavior of <code>str()</code>
here in respect to <code>app</code>.
</p>

<p><i>[2011-03-10: P.J.Plauger comments:]</i></p>


<p>I think we should say nothing special about <code>app</code> at construction
time (thus leaving the write pointer at the beginning of the buffer).
Leave implementers wiggle room to ensure subsequent append writes as they see 
fit, but don't change existing rules for initial seek position.</p>

<p><i>[Madrid meeting: It was observed that a different issue should be opened that
clarifies the meaning of <code>app</code> for <code>stringstream</code>]</i></p>



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

<p>Change 31.8.2.4 <a href="https://wg21.link/stringbuf.members">[stringbuf.members]</a> p. 3 as indicated:</p>

<blockquote><pre>
void str(const basic_string&lt;charT,traits,Allocator&gt;&amp; s);
</pre><blockquote>
<p>
2 <i>Effects</i>: Copies the content of <code>s</code> into the <code>basic_stringbuf</code> 
underlying character sequence and initializes the input and output sequences according 
to <code>mode</code>.
<p/>
3 <i>Postconditions</i>: If <code>mode &amp; ios_base::out</code> is true, <code>pbase()</code> 
points to the first underlying character and <code>epptr() &gt;= pbase() + s.size()</code> 
holds; in addition, if <code>mode &amp; <del>ios_base::in</del><ins>ios_base::ate</ins></code> 
is true, <code>pptr() == pbase() + <del>s.data()</del><ins>s.size()</ins></code> holds, 
otherwise <code>pptr() == pbase()</code> is true. If <code>mode &amp; ios_base::in</code> 
is true, <code>eback()</code> points to the first underlying character, and both 
<code>gptr() == eback() and egptr() == eback() + s.size()</code> 
hold.
</p>
</blockquote></blockquote>





</body>
</html>
