blob: 46a7f768500c7d362f92e7971eb85a463bb15d8e [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><title>C++ Standard Library Active Issues List</title></head>
<body bgcolor="#ffffff" text="#000000">
<table>
<tbody><tr>
<td align="left">Doc. no.</td>
<td align="left">N1762=05-0022</td>
</tr>
<tr>
<td align="left">Date:</td>
<td align="left">2005-03-04</td>
</tr>
<tr>
<td align="left">Project:</td>
<td align="left">Programming Language C++</td>
</tr>
<tr>
<td align="left">Reply to:</td>
<td align="left">Matt Austern &lt;austern@google.com&gt;</td>
</tr>
</tbody></table>
<h1>C++ Standard Library Active Issues List (Revision 35)</h1>
<p>Reference ISO/IEC IS 14882:1998(E)</p>
<p>Also see:</p>
<ul>
<li>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-toc.html">Table of Contents</a> for all library issues.</li>
<li>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-index.html">Index by Section</a> for all library issues.</li>
<li>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-status.html">Index by Status</a> for all library issues.</li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html">Library Defect Reports List</a></li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html">Library Closed Issues List</a></li>
</ul>
<p>The purpose of this document is to record the status of issues
which have come before the Library Working Group (LWG) of the ANSI
(J16) and ISO (WG21) C++ Standards Committee. Issues represent
potential defects in the ISO/IEC IS 14882:1998(E) document. Issues
are not to be used to request new features. </p>
<p>This document contains only library issues which are actively being
considered by the Library Working Group. That is, issues which have a
status of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>, and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a>. See
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html">Library Defect Reports List</a> for issues considered defects and
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html">Library Closed Issues List</a> for issues considered closed.</p>
<p>The issues in these lists are not necessarily formal ISO Defect
Reports (DR's). While some issues will eventually be elevated to
official Defect Report status, other issues will be disposed of in
other ways. See <a href="#Status">Issue Status</a>.</p>
<p>This document is in an experimental format designed for both
viewing via a world-wide web browser and hard-copy printing. It
is available as an HTML file for browsing or PDF file for
printing.</p>
<p>Prior to Revision 14, library issues lists existed in two slightly
different versions; a Committee Version and a Public
Version. Beginning with Revision 14 the two versions were combined
into a single version.</p>
<p>This document includes <i>[bracketed italicized notes]</i> as a
reminder to the LWG of current progress on issues. Such notes are
strictly unofficial and should be read with caution as they may be
incomplete or incorrect. Be aware that LWG support for a particular
resolution can quickly change if new viewpoints or killer examples are
presented in subsequent discussions.</p>
<p>For the most current official version of this document see
<a href="http://www.open-std.org/jtc1/sc22/wg21/">http://www.open-std.org/jtc1/sc22/wg21/</a>.
Requests for further information about this document should include
the document number above, reference ISO/IEC 14882:1998(E), and be
submitted to Information Technology Industry Council (ITI), 1250 Eye
Street NW, Washington, DC 20005.</p>
<p>Public information as to how to obtain a copy of the C++ Standard,
join the standards committee, submit an issue, or comment on an issue
can be found in the comp.std.c++ FAQ.
Public discussion of C++ Standard related issues occurs on <a href="news://comp.std.c++/">news:comp.std.c++</a>.
</p>
<p>For committee members, files available on the committee's private
web site include the HTML version of the Standard itself. HTML
hyperlinks from this issues list to those files will only work for
committee members who have downloaded them into the same disk
directory as the issues list files. </p>
<h2>Revision History</h2>
<ul>
<li>R35:
2005-03 pre-Lillehammer mailing.
</li>
<li>R34:
2005-01 mid-term mailing. Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#488">488</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#494">494</a>.
</li>
<li>R33:
2004-11 post-Redmond mailing. Reflections actions taken in Redmond.
</li>
<li>R32:
2004-09 pre-Redmond mailing: reflects new proposed resolutions and
new issues received after the 2004-07 mailing. Added
new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#479">479</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#481">481</a>.
</li>
<li>R31:
2004-07 mid-term mailing: reflects new proposed resolutions and
new issues received after the post-Sydney mailing. Added
new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#463">463</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#478">478</a>.
</li>
<li>R30:
Post-Sydney mailing: reflects decisions made at the Sydney meeting.
Voted all "Ready" issues from R29 into the working paper.
Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#460">460</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#462">462</a>.
</li>
<li>R29:
Pre-Sydney mailing. Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#441">441</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#457">457</a>.
</li>
<li>R28:
Post-Kona mailing: reflects decisions made at the Kona meeting.
Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#432">432</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#440">440</a>.
</li>
<li>R27:
Pre-Kona mailing. Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#404">404</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#431">431</a>.
</li>
<li>R26:
Post-Oxford mailing: reflects decisions made at the Oxford meeting.
All issues in Ready status were voted into DR status. All issues in
DR status were voted into WP status.
</li>
<li>R25:
Pre-Oxford mailing. Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#390">390</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#402">402</a>.
</li>
<li>R24:
Post-Santa Cruz mailing: reflects decisions made at the Santa Cruz
meeting. All Ready issues from R23 with the exception of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#253">253</a>, which has been given a new proposed resolution, were
moved to DR status. Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#383">383</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#389">389</a>. (Issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#387">387</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#389">389</a> were discussed
at the meeting.) Made progress on issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#225">225</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#226">226</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#229">229</a>: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#225">225</a> and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#229">229</a> have been moved to Ready status, and the only remaining
concerns with <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#226">226</a> involve wording.
</li>
<li>R23:
Pre-Santa Cruz mailing. Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#367">367</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#382">382</a>.
Moved issues in the TC to TC status.
</li>
<li>R22:
Post-Curaçao mailing. Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#362">362</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#366">366</a>.
</li>
<li>R21:
Pre-Curaçao mailing. Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#351">351</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#361">361</a>.
</li>
<li>R20:
Post-Redmond mailing; reflects actions taken in Redmond. Added
new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#336">336</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#350">350</a>, of which issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#347">347</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#350">350</a> were added since Redmond, hence
not discussed at the meeting.
All Ready issues were moved to DR status, with the exception of issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#284">284</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#241">241</a>, and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#267">267</a>.
Noteworthy issues discussed at Redmond include
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#120">120</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#202">202</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#226">226</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#233">233</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#270">270</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#253">253</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#254">254</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#323">323</a>.
</li>
<li>R19:
Pre-Redmond mailing. Added new issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#323">323</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#335">335</a>.
</li>
<li>R18:
Post-Copenhagen mailing; reflects actions taken in Copenhagen.
Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#312">312</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#317">317</a>, and discussed
new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#271">271</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#314">314</a>.
Changed status of issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#103">103</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#118">118</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#136">136</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#153">153</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#165">165</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#171">171</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#183">183</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#184">184</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#185">185</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#186">186</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#214">214</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#221">221</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#234">234</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#237">237</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#243">243</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#248">248</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#251">251</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#252">252</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#256">256</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#260">260</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#261">261</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#262">262</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#263">263</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#265">265</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#268">268</a>
to DR.
Changed status of issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#49">49</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#109">109</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#117">117</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#182">182</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#228">228</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#230">230</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#232">232</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#235">235</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#238">238</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#241">241</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#242">242</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#250">250</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#259">259</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#264">264</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#266">266</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#267">267</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#271">271</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#272">272</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#273">273</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#275">275</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#281">281</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#284">284</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#285">285</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#286">286</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#288">288</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#292">292</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#295">295</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#297">297</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#298">298</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#301">301</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#303">303</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#306">306</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#307">307</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#308">308</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#312">312</a>
to Ready.
Closed issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#111">111</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#277">277</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#279">279</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#287">287</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#289">289</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#293">293</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#302">302</a> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#313">313</a>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#314">314</a>
as NAD.
</li>
<li>R17:
Pre-Copenhagen mailing. Converted issues list to XML. Added proposed
resolutions for issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#49">49</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#76">76</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#91">91</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#235">235</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#250">250</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#267">267</a>.
Added new issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#278">278</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#311">311</a>.
</li>
<li>R16:
post-Toronto mailing; reflects actions taken in Toronto. Added new
issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#265">265</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#277">277</a>. Changed status of issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#3">3</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#8">8</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#9">9</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#19">19</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#26">26</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#31">31</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#61">61</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#63">63</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#86">86</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#108">108</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#112">112</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#114">114</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#115">115</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#122">122</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#127">127</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#129">129</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#134">134</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#137">137</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#142">142</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#144">144</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#146">146</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#147">147</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#159">159</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#164">164</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#170">170</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#181">181</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#199">199</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#208">208</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#209">209</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#210">210</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#211">211</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#212">212</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#217">217</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#220">220</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#222">222</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#223">223</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#224">224</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#227">227</a> to "DR". Reopened issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#23">23</a>. Reopened
issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#187">187</a>. Changed issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#2">2</a> and
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#4">4</a> to NAD. Fixed a typo in issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#17">17</a>. Fixed
issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#70">70</a>: signature should be changed both places it
appears. Fixed issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#160">160</a>: previous version didn't fix
the bug in enough places.
</li>
<li>R15:
pre-Toronto mailing. Added issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#233">233</a>-<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#264">264</a>. Some small HTML formatting
changes so that we pass Weblint tests.
</li>
<li>R14:
post-Tokyo II mailing; reflects committee actions taken in
Tokyo. Added issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#228">228</a> to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#232">232</a>. (00-0019R1/N1242)
</li>
<li>R13:
pre-Tokyo II updated: Added issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#212">212</a> to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#227">227</a>.
</li>
<li>R12:
pre-Tokyo II mailing: Added issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#199">199</a> to
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#211">211</a>. Added "and paragraph 5" to the proposed resolution
of issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#29">29</a>. Add further rationale to issue
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#178">178</a>.
</li>
<li>R11:
post-Kona mailing: Updated to reflect LWG and full committee actions
in Kona (99-0048/N1224). Note changed resolution of issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#4">4</a> and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#38">38</a>. Added issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#196">196</a>
to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#198">198</a>. Closed issues list split into "defects" and
"closed" documents. Changed the proposed resolution of issue
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#4">4</a> to NAD, and changed the wording of proposed resolution
of issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#38">38</a>.
</li>
<li>R10:
pre-Kona updated. Added proposed resolutions <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#83">83</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#86">86</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#91">91</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#92">92</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#109">109</a>. Added issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#190">190</a> to
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#195">195</a>. (99-0033/D1209, 14 Oct 99)
</li>
<li>R9:
pre-Kona mailing. Added issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#140">140</a> to
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#189">189</a>. Issues list split into separate "active" and
"closed" documents. (99-0030/N1206, 25 Aug 99)
</li>
<li>R8:
post-Dublin mailing. Updated to reflect LWG and full committee actions
in Dublin. (99-0016/N1193, 21 Apr 99)
</li>
<li>R7:
pre-Dublin updated: Added issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#130">130</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#131">131</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#132">132</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#133">133</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#134">134</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#135">135</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#136">136</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#137">137</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#138">138</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#139">139</a> (31 Mar 99)
</li>
<li>R6:
pre-Dublin mailing. Added issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#127">127</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#128">128</a>,
and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#129">129</a>. (99-0007/N1194, 22 Feb 99)
</li>
<li>R5:
update issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#103">103</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#112">112</a>; added issues
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#114">114</a> to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#126">126</a>. Format revisions to prepare
for making list public. (30 Dec 98)
</li>
<li>R4:
post-Santa Cruz II updated: Issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#110">110</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#111">111</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#112">112</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#113">113</a> added, several
issues corrected. (22 Oct 98)
</li>
<li>R3:
post-Santa Cruz II: Issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#94">94</a> to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#109">109</a>
added, many issues updated to reflect LWG consensus (12 Oct 98)
</li>
<li>R2:
pre-Santa Cruz II: Issues <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#73">73</a> to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#93">93</a> added,
issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#17">17</a> updated. (29 Sep 98)
</li>
<li>R1:
Correction to issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#55">55</a> resolution, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#60">60</a> code
format, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#64">64</a> title. (17 Sep 98)
</li>
</ul>
<h2>
<a name="Status"></a>Issue Status</h2>
<p><b><a name="New">New</a></b> - The issue has not yet been
reviewed by the LWG. Any <b>Proposed Resolution</b> is purely a
suggestion from the issue submitter, and should not be construed as
the view of LWG.</p>
<p><b><a name="Open">Open</a></b> - The LWG has discussed the issue
but is not yet ready to move the issue forward. There are several
possible reasons for open status:</p>
<ul>
<li>Consensus may have not yet have been reached as to how to deal
with the issue.</li>
<li>Informal consensus may have been reached, but the LWG awaits
exact <b>Proposed Resolution</b> wording for review.</li>
<li>The LWG wishes to consult additional technical experts before
proceeding.</li>
<li>The issue may require further study.</li>
</ul>
<p>A <b>Proposed Resolution</b> for an open issue is still not be
construed as the view of LWG. Comments on the current state of
discussions are often given at the end of open issues in an italic
font. Such comments are for information only and should not be given
undue importance.</p>
<p><b><a name="Dup">Dup</a></b> - The LWG has reached consensus that
the issue is a duplicate of another issue, and will not be further
dealt with. A <b>Rationale</b> identifies the duplicated issue's
issue number. </p>
<p><b><a name="NAD">NAD</a></b> - The LWG has reached consensus that
the issue is not a defect in the Standard, and the issue is ready to
forward to the full committee as a proposed record of response. A
<b>Rationale</b> discusses the LWG's reasoning.</p>
<p><b><a name="Review">Review</a></b> - Exact wording of a
<b>Proposed Resolution</b> is now available for review on an issue
for which the LWG previously reached informal consensus.</p>
<p><b><a name="Ready">Ready</a></b> - The LWG has reached consensus
that the issue is a defect in the Standard, the <b>Proposed
Resolution</b> is correct, and the issue is ready to forward to the
full committee for further action as a Defect Report (DR).</p>
<p><b><a name="DR">DR</a></b> - (Defect Report) - The full J16
committee has voted to forward the issue to the Project Editor to be
processed as a Potential Defect Report. The Project Editor reviews
the issue, and then forwards it to the WG21 Convenor, who returns it
to the full committee for final disposition. This issues list
accords the status of DR to all these Defect Reports regardless of
where they are in that process.</p>
<p><b><a name="TC">TC</a></b> - (Technical Corrigenda) - The full
WG21 committee has voted to accept the Defect Report's Proposed
Resolution as a Technical Corrigenda. Action on this issue is thus
complete and no further action is possible under ISO rules.</p>
<p><b><a name="WP">WP</a></b> - (Working Paper) - The proposed
resolution has not been accepted as a Technical Corrigendum, but
the full WG21 committee has voted to apply the Defect Report's Proposed
Resolution to the working paper.</p>
<p><b><a name="RR">RR</a></b> - (Record of Response) - The full WG21
committee has determined that this issue is not a defect in the
Standard. Action on this issue is thus complete and no further
action is possible under ISO rules.</p>
<p><b><a name="Future">Future</a></b> - In addition to the regular
status, the LWG believes that this issue should be revisited at the
next revision of the standard. It is usually paired with NAD.</p>
<p>Issues are always given the status of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> when
they first appear on the issues list. They may progress to
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> or <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a> while the LWG
is actively working on them. When the LWG has reached consensus on
the disposition of an issue, the status will then change to
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Dup">Dup</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#NAD">NAD</a>, or <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> as appropriate. Once the full J16 committee votes to
forward Ready issues to the Project Editor, they are given the
status of Defect Report ( <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#DR">DR</a>). These in turn may
become the basis for Technical Corrigenda (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#TC">TC</a>),
or are closed without action other than a Record of Response
(<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#RR">RR</a> ). The intent of this LWG process is that
only issues which are truly defects in the Standard move to the
formal ISO DR status.
</p>
<h2>Active Issues</h2>
<hr>
<a name="23"><h3>23.&nbsp;Num_get overflow result</h3></a><p><b>Section:</b>&nbsp;22.2.2.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.facet.num.get.virtuals"> [lib.facet.num.get.virtuals]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Nathan Myers&nbsp; <b>Date:</b>&nbsp;6 Aug 1998</p>
<p>The current description of numeric input does not account for the
possibility of overflow. This is an implicit result of changing the
description to rely on the definition of scanf() (which fails to
report overflow), and conflicts with the documented behavior of
traditional and current implementations. </p>
<p>Users expect, when reading a character sequence that results in a
value unrepresentable in the specified type, to have an error
reported. The standard as written does not permit this. </p>
<p><b>Further comments from Dietmar:</b></p>
<p>
I don't feel comfortable with the proposed resolution to issue 23: It
kind of simplifies the issue to much. Here is what is going on:
</p>
<p>
Currently, the behavior of numeric overflow is rather counter intuitive
and hard to trace, so I will describe it briefly:
</p>
<ul>
<li>
According to 22.2.2.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.facet.num.get.virtuals"> [lib.facet.num.get.virtuals]</a>
paragraph 11 <tt>failbit</tt> is set if <tt>scanf()</tt> would
return an input error; otherwise a value is converted to the rules
of <tt>scanf</tt>.
</li>
<li>
<tt>scanf()</tt> is defined in terms of <tt>fscanf()</tt>.
</li>
<li>
<tt>fscanf()</tt> returns an input failure if during conversion no
character matching the conversion specification could be extracted
before reaching EOF. This is the only reason for <tt>fscanf()</tt>
to fail due to an input error and clearly does not apply to the case
of overflow.
</li>
<li>
Thus, the conversion is performed according to the rules of
<tt>fscanf()</tt> which basically says that <tt>strtod</tt>,
<tt>strtol()</tt>, etc. are to be used for the conversion.
</li>
<li>
The <tt>strtod()</tt>, <tt>strtol()</tt>, etc. functions consume as
many matching characters as there are and on overflow continue to
consume matching characters but also return a value identical to
the maximum (or minimum for signed types if there was a leading minus)
value of the corresponding type and set <tt>errno</tt> to <tt>ERANGE</tt>.
</li>
<li>
Thus, according to the current wording in the standard, overflows
can be detected! All what is to be done is to check <tt>errno</tt>
after reading an element and, of course, clearing <tt>errno</tt>
before trying a conversion. With the current wording, it can be
detected whether the overflow was due to a positive or negative
number for signed types.
</li>
</ul>
<p><b>Further discussion from Redmond:</b></p>
<p>The basic problem is that we've defined our behavior,
including our error-reporting behavior, in terms of C90. However,
C90's method of reporting overflow in scanf is not technically an
"input error". The <tt>strto_*</tt> functions are more precise.</p>
<p>There was general consensus that <tt>failbit</tt> should be set
upon overflow. We considered three options based on this:</p>
<ol>
<li>Set failbit upon conversion error (including overflow), and
don't store any value.</li>
<li>Set failbit upon conversion error, and also set <tt>errno</tt> to
indicated the precise nature of the error.</li>
<li>Set failbit upon conversion error. If the error was due to
overflow, store +-numeric_limits&lt;T&gt;::max() as an
overflow indication.</li>
</ol>
<p>Straw poll: (1) 5; (2) 0; (3) 8.</p>
<p><b>Further discussion from Santa Cruz:</b></p>
<p>There was some discussion of what the intent of our error
reporting mechanism was. There was general agreement on the
following principles:</p>
<ul>
<li>We want to convert strings to numbers in the same way as the
C <tt>strto*</tt> functions do. The same things that those
functions would consider errors, we consider errors.</li>
<li>Overflow is an error. Floating-point underflow is not an error.
1.e-9999999, for example, should be treated as 0. (A negative
number whose magnitude is too large is still overflow, and is just
the same error as a positive number whose magnitude is too large.
Finally, <tt>strtoul</tt> already specifies what happens if you
try to convert a sequence beginning with a minus sign into an
unsigned value.)</li>
<li>Our mechanism for reporting errors is to set failbit. Our
mechanism is not errno. Nothing in the standard should
require or imply that streams or facets ever set errno.
(Even if some implementations might have that effect.) </li>
</ul>
<p>The crux of the disagreement was that some people, but not all,
believed that the design was also based on a fourth principle:
whenever converstion fails and failbit is set, nothing is to be
extracted and the value of the variable being extracted into is
guaranteed to be unchanged.</p>
<p>Some people believe that upon overflow, an implementation should
"extract" a special value that allows the user to tell that it was
overflow instead of some other kind of error. Straw poll: 1 person
believed the standard should require that, 2 thought it should
forbid it, and 6 thought the standard should allow but not require
it.</p>
<p><b>Proposed resolution:</b></p>
<p>typo: 22.2.2.2.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.facet.num.put.virtuals"> [lib.facet.num.put.virtuals]</a>, para 2, bullet 3. Strike "in." from
the end.</p>
<p>Change 22.2.2.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.locale.nm.put"> [lib.locale.nm.put]</a>, para 11, bullet 2 from:</p>
<blockquote>
The sequence of chars accumulated in stage 2 would have
caused scanf to report an input failure. ios_base::failbit is
assigned to err.
</blockquote>
<p>to:</p>
<blockquote>
The sequence of chars accumulated in stage 2 would have
caused scanf to report an input failure or to store a value
outside the range representable by val. ios_base::failbit is
assigned to err.
</blockquote>
<p><i>[PJP provided wording. this treats overflow or underflow the same
as an ill-formed field. It's not exactly the consensus from Santa
Cruz, but he thinks it's the simplest and most robust rule and that it
corresponds to widespread common practice.]</i></p>
<p><i>[Kona: Wording here still isn't quite right, partly because it
refers to scanf and the scanf description of error conditions is
murky. The LWG had to do a very close reading of scanf in an attempt
to figure out what this proposed resolution means. General agreement
that the correct solution: (1) should not refer to scanf behavior, (2)
should not set errno, (3) should allow users who care to figure out
what kind of error happened. Martin will provide wording, Howard may
help.]</i></p>
<hr>
<a name="96"><h3>96.&nbsp;Vector&lt;bool&gt; is not a container</h3></a><p><b>Section:</b>&nbsp;23.2.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.bool"> [lib.vector.bool]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;AFNOR&nbsp; <b>Date:</b>&nbsp;7 Oct 1998</p>
<p><tt>vector&lt;bool&gt;</tt> is not a container as its reference and
pointer types are not references and pointers. </p>
<p>Also it forces everyone to have a space optimization instead of a
speed one.</p>
<p><b>See also:</b> 99-0008 == N1185 Vector&lt;bool&gt; is
Nonconforming, Forces Optimization Choice.</p>
<p><b>Proposed resolution:</b></p>
<p><i>[In Santa Cruz the LWG felt that this was Not A Defect.]</i></p>
<p><i>[In Dublin many present felt that failure to meet Container
requirements was a defect. There was disagreement as to whether
or not the optimization requirements constituted a defect.]</i></p>
<p><i>[The LWG looked at the following resolutions in some detail:
<br>
&nbsp;&nbsp;&nbsp;&nbsp; * Not A Defect.<br>
&nbsp;&nbsp;&nbsp;&nbsp; * Add a note explaining that vector&lt;bool&gt; does not meet
Container requirements.<br>
&nbsp;&nbsp;&nbsp;&nbsp; * Remove vector&lt;bool&gt;.<br>
&nbsp;&nbsp;&nbsp;&nbsp; * Add a new category of container requirements which
vector&lt;bool&gt; would meet.<br>
&nbsp;&nbsp;&nbsp;&nbsp; * Rename vector&lt;bool&gt;.<br>
<br>
No alternative had strong, wide-spread, support and every alternative
had at least one "over my dead body" response.<br>
<br>
There was also mention of a transition scheme something like (1) add
vector_bool and deprecate vector&lt;bool&gt; in the next standard. (2)
Remove vector&lt;bool&gt; in the following standard.]</i></p>
<p><i>[Modifying container requirements to permit returning proxies
(thus allowing container requirements conforming vector&lt;bool&gt;)
was also discussed.]</i></p>
<p><i>[It was also noted that there is a partial but ugly workaround in
that vector&lt;bool&gt; may be further specialized with a customer
allocator.]</i></p>
<p><i>[Kona: Herb Sutter presented his paper J16/99-0035==WG21/N1211,
vector&lt;bool&gt;: More Problems, Better Solutions. Much discussion
of a two step approach: a) deprecate, b) provide replacement under a
new name. LWG straw vote on that: 1-favor, 11-could live with, 2-over
my dead body. This resolution was mentioned in the LWG report to the
full committee, where several additional committee members indicated
over-my-dead-body positions.]</i></p>
<p><i>[Tokyo: Not discussed by the full LWG; no one claimed new
insights and so time was more productively spent on other issues. In
private discussions it was asserted that requirements for any solution
include 1) Increasing the full committee's understanding of the
problem, and 2) providing compiler vendors, authors, teachers, and of
course users with specific suggestions as to how to apply the eventual
solution.]</i></p>
<p><i>[Redmond: briefly discussed, since there are options for C++0x
that weren't reasonable for TC1. Two options were discussed. (1)
deprecate std::vector&lt;bool&gt; and introduce std::bit_vector. Then
gradually, over a period of years, we could reintroduce
std::vector&lt;bool&gt; but this time as an ordinary vector. (2) Change
iterarator and container requirements so that vector&lt;bool&gt; will
be a fully conforming container. These options are not mutually
exclusive.]</i></p>
<hr>
<a name="130"><h3>130.&nbsp;Return type of container::erase(iterator) differs for associative containers</h3></a><p><b>Section:</b>&nbsp;23.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a>, 23.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.sequence.reqmts"> [lib.sequence.reqmts]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Andrew Koenig&nbsp; <b>Date:</b>&nbsp;2 Mar 1999</p>
<p>Table 67 (23.1.1) says that container::erase(iterator) returns an
iterator. Table 69 (23.1.2) says that in addition to this requirement,
associative containers also say that container::erase(iterator)
returns void. That's not an addition; it's a change to the
requirements, which has the effect of making associative containers
fail to meet the requirements for containers.</p>
<p><b>Proposed resolution:</b></p>
<p>
In 23.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a>, in Table 69 Associative container
requirements, change the return type of <tt>a.erase(q)</tt> from
<tt>void</tt> to <tt>iterator</tt>. Change the
assertion/not/pre/post-condition from "erases the element pointed to
by <tt>q</tt>" to "erases the element pointed to by <tt>q</tt>.
Returns an iterator pointing to the element immediately following q
prior to the element being erased. If no such element exists, a.end()
is returned."
</p>
<p>
In 23.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a>, in Table 69 Associative container
requirements, change the return type of <tt>a.erase(q1, q2)</tt>
from <tt>void</tt> to <tt>iterator</tt>. Change the
assertion/not/pre/post-condition from "erases the elements in the
range <tt>[q1, q2)</tt>" to "erases the elements in the range <tt>[q1,
q2)</tt>. Returns q2."
</p>
<p>
In 23.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.map"> [lib.map]</a>, in the <tt>map</tt> class synopsis; and
in 23.3.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.multimap"> [lib.multimap]</a>, in the <tt>multimap</tt> class synopsis; and
in 23.3.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.set"> [lib.set]</a>, in the <tt>set</tt> class synopsis; and
in 23.3.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.multiset"> [lib.multiset]</a>, in the <tt>multiset</tt> class synopsis:
change the signature of the first <tt>erase</tt> overload to
</p>
<pre> iterator erase(iterator position);
</pre>
<p>and change the signature of the third <tt>erase</tt> overload to</p>
<pre> iterator erase(iterator first, iterator last);
</pre>
<p><i>[Pre-Kona: reopened at the request of Howard Hinnant]</i></p>
<p><i>[Post-Kona: the LWG agrees the return type should be
<tt>iterator</tt>, not <tt>void</tt>. (Alex Stepanov agrees too.)
Matt provided wording.]</i></p>
<p><i>[
Sydney: the proposed wording went in the right direction, but it
wasn't good enough. We want to return an iterator from the range form
of erase as well as the single-iterator form. Also, the wording is
slightly different from the wording we have for sequences; there's no
good reason for having a difference. Matt provided new wording,
which we will review at the next meeting.
]</i></p>
<hr>
<a name="197"><h3>197.&nbsp;max_size() underspecified</h3></a><p><b>Section:</b>&nbsp;20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a>, 23.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Andy Sawyer&nbsp; <b>Date:</b>&nbsp;21 Oct 1999</p>
<p>Must the value returned by max_size() be unchanged from call to call? </p>
<p>Must the value returned from max_size() be meaningful? </p>
<p>Possible meanings identified in lib-6827: </p>
<p>1) The largest container the implementation can support given "best
case" conditions - i.e. assume the run-time platform is "configured to
the max", and no overhead from the program itself. This may possibly
be determined at the point the library is written, but certainly no
later than compile time.<br>
<br>
2) The largest container the program could create, given "best case"
conditions - i.e. same platform assumptions as (1), but take into
account any overhead for executing the program itself. (or, roughly
"storage=storage-sizeof(program)"). This does NOT include any resource
allocated by the program. This may (or may not) be determinable at
compile time.<br>
<br>
3) The largest container the current execution of the program could
create, given knowledge of the actual run-time platform, but again,
not taking into account any currently allocated resource. This is
probably best determined at program start-up.<br>
<br>
4) The largest container the current execution program could create at
the point max_size() is called (or more correctly at the point
max_size() returns :-), given it's current environment (i.e. taking
into account the actual currently available resources). This,
obviously, has to be determined dynamically each time max_size() is
called. </p>
<p><b>Proposed resolution:</b></p>
<p>Change 20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a> table 32 max_size() wording from:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the largest value that can meaningfully be
passed to X::allocate<br>
to:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the value of the largest constant expression
(5.19 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/expr.html#expr.const"> [expr.const]</a>) that could ever meaningfully be passed to X::allocate</p>
<p>
Change 23.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a> table 65 max_size() wording from:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size() of the largest possible container.<br>
to:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the value of the largest constant expression
(5.19 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/expr.html#expr.const"> [expr.const]</a>) that could ever meaningfully be returned by X::size().
</p>
<p><i>[Kona: The LWG informally discussed this and asked Andy Sawyer to submit
an issue.]</i></p>
<p><i>[Tokyo: The LWG believes (1) above is the intended meaning.]</i></p>
<p><i>[Post-Tokyo: Beman Dawes supplied the above resolution at the
request of the LWG. 21.3.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-strings.html#lib.string.capacity"> [lib.string.capacity]</a> was not changed because it
references max_size() in 23.1. The term "compile-time" was
avoided because it is not defined anywhere in the standard (even
though it is used several places in the library clauses).]</i></p>
<p><i>[Copenhagen: Exactly what <tt>max_size</tt> means is still
unclear. It may have a different meaning as a container member
function than as an allocator member function. For the latter,
it is probably best thought of as an architectural limit.
Nathan will provide new wording.]</i></p>
<hr>
<a name="201"><h3>201.&nbsp;Numeric limits terminology wrong</h3></a><p><b>Section:</b>&nbsp;18.2.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-support.html#lib.limits"> [lib.limits]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Stephen Cleary&nbsp; <b>Date:</b>&nbsp;21 Dec 1999</p>
<p>
In some places in this section, the terms "fundamental types" and
"scalar types" are used when the term "arithmetic types" is intended.
The current usage is incorrect because void is a fundamental type and
pointers are scalar types, neither of which should have
specializations of numeric_limits.
</p>
<p><b>Proposed resolution:</b></p>
<p>Change 18.2 [lib.support.limits] para 1 from:</p>
<blockquote>
<p> The headers &lt;limits&gt;, &lt;climits&gt;, and &lt;cfloat&gt;
supply characteristics of implementation-dependent fundamental types
(3.9.1).</p>
</blockquote>
<p>to:</p>
<blockquote>
<p> The headers &lt;limits&gt;, &lt;climits&gt;, and &lt;cfloat&gt;
supply characteristics of implementation-dependent arithmetic types
(3.9.1).</p>
</blockquote>
<p>Change 18.2.1 [lib.limits] para 1 from:</p>
<blockquote>
<p> The numeric_limits component provides a C++ program with
information about various properties of the implementation's
representation of the fundamental
types.</p>
</blockquote>
<p>to:</p>
<blockquote>
<p> The numeric_limits component provides a C++ program with
information about various properties of the implementation's
representation of the arithmetic
types.</p>
</blockquote>
<p>Change 18.2.1 [lib.limits] para 2 from:</p>
<blockquote>
<p> Specializations shall be provided for each fundamental type. . .</p>
</blockquote>
<p>to:</p>
<blockquote>
<p> Specializations shall be provided for each arithmetic type. . .</p>
</blockquote>
<p>Change 18.2.1 [lib.limits] para 4 from:</p>
<blockquote>
<p> Non-fundamental standard types. . .</p>
</blockquote>
<p>to:</p>
<blockquote>
<p> Non-arithmetic standard types. . .</p>
</blockquote>
<p>Change 18.2.1.1 [lib.numeric.limits] para 1 from:</p>
<blockquote>
<p> The member is_specialized makes it possible to distinguish between
fundamental types, which have specializations, and non-scalar types,
which
do not.</p>
</blockquote>
<p>to:</p>
<blockquote>
<p> The member is_specialized makes it possible to distinguish between
arithmetic types, which have specializations, and non-arithmetic types,
which do not.</p>
</blockquote>
<p><i>[post-Toronto: The opinion of the LWG is that the wording in the
standard, as well as the wording of the proposed resolution, is
flawed. The term "arithmetic types" is well defined in C
and C++, and it is not clear that the term is being used correctly.
It is also not clear that the term "implementation
dependent" has any useful meaning in this context. The biggest
problem is that numeric_limits seems to be intended both for built-in
types and for user-defined types, and the standard doesn't make it
clear how numeric_limits applies to each of those cases. A wholesale
review of numeric_limits is needed. A paper would be welcome.]</i></p>
<hr>
<a name="233"><h3>233.&nbsp;Insertion hints in associative containers</h3></a><p><b>Section:</b>&nbsp;23.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Andrew Koenig&nbsp; <b>Date:</b>&nbsp;30 Apr 2000</p>
<p>
If <tt>mm</tt> is a multimap and <tt>p</tt> is an iterator
into the multimap, then <tt>mm.insert(p, x)</tt> inserts
<tt>x</tt> into <tt>mm</tt> with <tt>p</tt> as a hint as
to where it should go. Table 69 claims that the execution time is
amortized constant if the insert winds up taking place adjacent to
<tt>p</tt>, but does not say when, if ever, this is guaranteed to
happen. All it says it that <tt>p</tt> is a hint as to where to
insert.
</p>
<p>
The question is whether there is any guarantee about the relationship
between <tt>p</tt> and the insertion point, and, if so, what it
is.
</p>
<p>
I believe the present state is that there is no guarantee: The user
can supply <tt>p</tt>, and the implementation is allowed to
disregard it entirely.
</p>
<p><b>Additional comments from Nathan:</b><br>
The vote [in Redmond] was on whether to elaborately specify the use of
the hint, or to require behavior only if the value could be inserted
adjacent to the hint. I would like to ensure that we have a chance to
vote for a deterministic treatment: "before, if possible, otherwise
after, otherwise anywhere appropriate", as an alternative to the
proposed "before or after, if possible, otherwise [...]".
</p>
<p><b>Proposed resolution:</b></p>
<p>In table 69 "Associative Container Requirements" in 23.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a>, in the row for <tt>a.insert(p, t)</tt>,
change</p>
<blockquote>
iterator p is a hint pointing to where the insert
should start to search.
</blockquote>
<p>to</p>
<blockquote>
insertion adjacent to iterator p is preferred if
more than one insertion point is valid.
</blockquote>
<p>and change</p>
<blockquote>
logarithmic in general, but amortized constant if
t is inserted right after p.
</blockquote>
<p>to</p>
<blockquote>
logarithmic in general, but amortized constant if
t is inserted adjacent to iterator p.
</blockquote>
<p><i>[Toronto: there was general agreement that this is a real defect:
when inserting an element x into a multiset that already contains
several copies of x, there is no way to know whether the hint will be
used. The proposed resolution was that the new element should always
be inserted as close to the hint as possible. So, for example, if
there is a subsequence of equivalent values, then providing a.begin()
as the hint means that the new element should be inserted before the
subsequence even if a.begin() is far away. JC van Winkel supplied
precise wording for this proposed resolution, and also for an
alternative resolution in which hints are only used when they are
adjacent to the insertion point.]</i></p>
<p><i>[Copenhagen: the LWG agreed to the original proposed resolution,
in which an insertion hint would be used even when it is far from the
insertion point. This was contingent on seeing a reference
implementation showing that it is possible to implement this
requirement without loss of efficiency. John Potter provided such a
reference implementation.]</i></p>
<p><i>[Redmond: The LWG was reluctant to adopt the proposal that
emerged from Copenhagen: it seemed excessively complicated, and went
beyond fixing the defect that we identified in Toronto. PJP provided
the new wording described in this issue. Nathan agrees that we
shouldn't adopt the more detailed semantics, and notes: "we know that
you can do it efficiently enough with a red-black tree, but there are
other (perhaps better) balanced tree techniques that might differ
enough to make the detailed semantics hard to satisfy."]</i></p>
<p><i>[Curaçao: Nathan should give us the alternative wording he
suggests so the LWG can decide between the two options.]</i></p>
<hr>
<a name="247"><h3>247.&nbsp;<tt>vector</tt>, <tt>deque::insert</tt> complexity</h3></a><p><b>Section:</b>&nbsp;23.2.4.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.modifiers"> [lib.vector.modifiers]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Lisa Lippincott&nbsp; <b>Date:</b>&nbsp;06 June 2000</p>
<p>Paragraph 2 of 23.2.4.3 [lib.vector.modifiers] describes the complexity
of <tt>vector::insert</tt>:</p>
<blockquote>
Complexity: If first and last are forward iterators, bidirectional
iterators, or random access iterators, the complexity is linear in
the number of elements in the range [first, last) plus the distance
to the end of the vector. If they are input iterators, the complexity
is proportional to the number of elements in the range [first, last)
times the distance to the end of the vector.
</blockquote>
<p>First, this fails to address the non-iterator forms of
<tt>insert</tt>.</p>
<p>Second, the complexity for input iterators misses an edge case --
it requires that an arbitrary number of elements can be added at
the end of a <tt>vector</tt> in constant time.</p>
<p>At the risk of strengthening the requirement, I suggest simply</p>
<blockquote>
Complexity: The complexity is linear in the number of elements
inserted plus the distance to the end of the vector.
</blockquote>
<p>For input iterators, one may achieve this complexity by first
inserting at the end of the <tt>vector</tt>, and then using
<tt>rotate</tt>.</p>
<p>I looked to see if <tt>deque</tt> had a similar problem, and was
surprised to find that <tt>deque</tt> places no requirement on the
complexity of inserting multiple elements (23.2.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.deque.modifiers"> [lib.deque.modifiers]</a>,
paragraph 3):</p>
<blockquote>
Complexity: In the worst case, inserting a single element into a
deque takes time linear in the minimum of the distance from the
insertion point to the beginning of the deque and the distance
from the insertion point to the end of the deque. Inserting a
single element either at the beginning or end of a deque always
takes constant time and causes a single call to the copy constructor
of T.
</blockquote>
<p>I suggest:</p>
<blockquote>
Complexity: The complexity is linear in the number of elements
inserted plus the shorter of the distances to the beginning and
end of the deque. Inserting a single element at either the
beginning or the end of a deque causes a single call to the copy
constructor of T.
</blockquote>
<p><b>Proposed resolution:</b></p>
<p><i>[Toronto: It's agreed that there is a defect in complexity of
multi-element insert for vector and deque. For vector, the complexity
should probably be something along the lines of <tt>c<sub>1</sub> * N
+ c<sub>2</sub> * distance(i, end())</tt>. However, there is some
concern about whether it is reasonable to amortize away the copies
that we get from a reallocation whenever we exceed the vector's
capacity. For deque, the situation is somewhat less clear. Deque is
notoriously complicated, and we may not want to impose complexity
requirements that would imply any implementation technique more
complicated than a while loop whose body is a single-element
insert.]</i></p>
<hr>
<a name="254"><h3>254.&nbsp;Exception types in clause 19 are constructed from <tt>std::string</tt>
</h3></a><p><b>Section:</b>&nbsp;19.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-diagnostics.html#lib.std.exceptions"> [lib.std.exceptions]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Dave Abrahams&nbsp; <b>Date:</b>&nbsp;01 Aug 2000</p>
<p>
Many of the standard exception types which implementations are
required to throw are constructed with a const std::string&amp;
parameter. For example:
</p>
<pre> 19.1.5 Class out_of_range [lib.out.of.range]
namespace std {
class out_of_range : public logic_error {
public:
explicit out_of_range(const string&amp; what_arg);
};
}
1 The class out_of_range defines the type of objects thrown as excep-
tions to report an argument value not in its expected range.
out_of_range(const string&amp; what_arg);
Effects:
Constructs an object of class out_of_range.
Postcondition:
strcmp(what(), what_arg.c_str()) == 0.
</pre>
<p>
There are at least two problems with this:
</p>
<ol>
<li>A program which is low on memory may end up throwing
std::bad_alloc instead of out_of_range because memory runs out while
constructing the exception object.</li>
<li>An obvious implementation which stores a std::string data member
may end up invoking terminate() during exception unwinding because the
exception object allocates memory (or rather fails to) as it is being
copied.</li>
</ol>
<p>
There may be no cure for (1) other than changing the interface to
out_of_range, though one could reasonably argue that (1) is not a
defect. Personally I don't care that much if out-of-memory is reported
when I only have 20 bytes left, in the case when out_of_range would
have been reported. People who use exception-specifications might care
a lot, though.
</p>
<p>
There is a cure for (2), but it isn't completely obvious. I think a
note for implementors should be made in the standard. Avoiding
possible termination in this case shouldn't be left up to chance. The
cure is to use a reference-counted "string" implementation
in the exception object. I am not necessarily referring to a
std::string here; any simple reference-counting scheme for a NTBS
would do.
</p>
<p><b>Further discussion, in email:</b></p>
<p>
...I'm not so concerned about (1). After all, a library implementation
can add const char* constructors as an extension, and users don't
<i>need</i> to avail themselves of the standard exceptions, though this is
a lame position to be forced into. FWIW, std::exception and
std::bad_alloc don't require a temporary basic_string.
</p>
<p>
...I don't think the fixed-size buffer is a solution to the problem,
strictly speaking, because you can't satisfy the postcondition
<br>
<tt>&nbsp;&nbsp;strcmp(what(), what_arg.c_str()) == 0</tt>
<br>
For all values of what_arg (i.e. very long values). That means that
the only truly conforming solution requires a dynamic allocation.
</p>
<p><b>Further discussion, from Redmond:</b></p>
<p>The most important progress we made at the Redmond meeting was
realizing that there are two separable issues here: the const
string&amp; constructor, and the copy constructor. If a user writes
something like <tt>throw std::out_of_range("foo")</tt>, the const
string&amp; constructor is invoked before anything gets thrown. The
copy constructor is potentially invoked during stack unwinding.</p>
<p>The copy constructor is a more serious problem, becuase failure
during stack unwinding invokes <tt>terminate</tt>. The copy
constructor must be nothrow. <i>Curaçao: Howard thinks this
requirement may already be present.</i></p>
<p>The fundamental problem is that it's difficult to get the nothrow
requirement to work well with the requirement that the exception
objects store a string of unbounded size, particularly if you also try
to make the const string&amp; constructor nothrow. Options discussed
include:</p>
<ul>
<li>Limit the size of a string that exception objects are required to
throw: change the postconditions of 19.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-diagnostics.html#lib.domain.error"> [lib.domain.error]</a> paragraph 3
and 19.1.6 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-diagnostics.html#lib.runtime.error"> [lib.runtime.error]</a> paragraph 3 to something like this:
"strncmp(what(), what_arg._str(), N) == 0, where N is an
implementation defined constant no smaller than 256".</li>
<li>Allow the const string&amp; constructor to throw, but not the
copy constructor. It's the implementor's responsibility to get it
right. (An implementor might use a simple refcount class.)</li>
<li>Compromise between the two: an implementation is not allowed to
throw if the string's length is less than some N, but, if it doesn't
throw, the string must compare equal to the argument.</li>
<li>Add a new constructor that takes a const char*</li>
</ul>
<p>(Not all of these options are mutually exclusive.)</p>
<p><b>Proposed resolution:</b></p>
<p><b>Rationale:</b></p>
<p>Throwing a bad_alloc while trying to construct a message for another
exception-derived class is not necessarily a bad thing. And the
bad_alloc constructor already has a no throw spec on it (18.4.2.1).</p>
<p><b>Future:</b></p>
<p>All involved would like to see const char* constructors added, but
this should probably be done for C++0X as opposed to a DR.</p>
<p>I believe the no throw specs currently decorating these functions
could be improved by some kind of static no throw spec checking
mechanism (in a future C++ language). As they stand, the copy
constructors might fail via a call to unexpected. I think what is
intended here is that the copy constructors can't fail.</p>
<p><i>[Pre-Sydney: reopened at the request of Howard Hinnant.
Post-Redmond: James Kanze noticed that the copy constructors of
exception-derived classes do not have nothrow clauses. Those
classes have no copy constructors declared, meaning the
compiler-generated implicit copy constructors are used, and those
compiler-generated constructors might in principle throw anything.]</i></p>
<hr>
<a name="258"><h3>258.&nbsp;Missing allocator requirement</h3></a><p><b>Section:</b>&nbsp;20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Matt Austern&nbsp; <b>Date:</b>&nbsp;22 Aug 2000</p>
<p>
From lib-7752:
</p>
<p>
I've been assuming (and probably everyone else has been assuming) that
allocator instances have a particular property, and I don't think that
property can be deduced from anything in Table 32.
</p>
<p>
I think we have to assume that allocator type conversion is a
homomorphism. That is, if x1 and x2 are of type X, where
X::value_type is T, and if type Y is X::template
rebind&lt;U&gt;::other, then Y(x1) == Y(x2) if and only if x1 == x2.
</p>
<p>
Further discussion: Howard Hinnant writes, in lib-7757:
</p>
<p>
I think I can prove that this is not provable by Table 32. And I agree
it needs to be true except for the "and only if". If x1 != x2, I see no
reason why it can't be true that Y(x1) == Y(x2). Admittedly I can't
think of a practical instance where this would happen, or be valuable.
But I also don't see a need to add that extra restriction. I think we
only need:
</p>
<blockquote>
if (x1 == x2) then Y(x1) == Y(x2)
</blockquote>
<p>
If we decide that == on allocators is transitive, then I think I can
prove the above. But I don't think == is necessarily transitive on
allocators. That is:
</p>
<p>
Given x1 == x2 and x2 == x3, this does not mean x1 == x3.
</p>
<p>Example:</p>
<blockquote>
<p>
x1 can deallocate pointers from: x1, x2, x3 <br>
x2 can deallocate pointers from: x1, x2, x4 <br>
x3 can deallocate pointers from: x1, x3 <br>
x4 can deallocate pointers from: x2, x4
</p>
<p>
x1 == x2, and x2 == x4, but x1 != x4
</p>
</blockquote>
<p><b>Proposed resolution:</b></p>
<p><i>[Toronto: LWG members offered multiple opinions. One
opinion is that it should not be required that <tt>x1 == x2</tt>
implies <tt>Y(x1) == Y(x2)</tt>, and that it should not even be
required that <tt>X(x1) == x1</tt>. Another opinion is that
the second line from the bottom in table 32 already implies the
desired property. This issue should be considered in light of
other issues related to allocator instances.]</i></p>
<hr>
<a name="280"><h3>280.&nbsp;Comparison of reverse_iterator to const reverse_iterator</h3></a><p><b>Section:</b>&nbsp;24.4.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.reverse.iterators"> [lib.reverse.iterators]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Steve Cleary&nbsp; <b>Date:</b>&nbsp;27 Nov 2000</p>
<p>
This came from an email from Steve Cleary to Fergus in reference to
issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#179">179</a>. The library working group briefly discussed
this in Toronto and believed it should be a separate issue. There was
also some reservations about whether this was a worthwhile problem to
fix.
</p>
<p>
Steve said: "Fixing reverse_iterator. std::reverse_iterator can
(and should) be changed to preserve these additional
requirements." He also said in email that it can be done without
breaking user's code: "If you take a look at my suggested
solution, reverse_iterator doesn't have to take two parameters; there
is no danger of breaking existing code, except someone taking the
address of one of the reverse_iterator global operator functions, and
I have to doubt if anyone has ever done that. . . <i>But</i>, just in
case they have, you can leave the old global functions in as well --
they won't interfere with the two-template-argument functions. With
that, I don't see how <i>any</i> user code could break."
</p>
<p><b>Proposed resolution:</b></p>
<p>
<b>Section:</b> 24.4.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.reverse.iterator"> [lib.reverse.iterator]</a>
add/change the following declarations:</p>
<pre> A) Add a templated assignment operator, after the same manner
as the templated copy constructor, i.e.:
template &lt; class U &gt;
reverse_iterator &lt; Iterator &gt;&amp; operator=(const reverse_iterator&lt; U &gt;&amp; u);
B) Make all global functions (except the operator+) have
two template parameters instead of one, that is, for
operator ==, !=, &lt;, &gt;, &lt;=, &gt;=, - replace:
template &lt; class Iterator &gt;
typename reverse_iterator&lt; Iterator &gt;::difference_type operator-(
const reverse_iterator&lt; Iterator &gt;&amp; x,
const reverse_iterator&lt; Iterator &gt;&amp; y);
with:
template &lt; class Iterator1, class Iterator2 &gt;
typename reverse_iterator &lt; Iterator1 &gt;::difference_type operator-(
const reverse_iterator &lt; Iterator1 &gt; &amp; x,
const reverse_iterator &lt; Iterator2 &gt; &amp; y);
</pre>
<p>
Also make the addition/changes for these signatures in
24.4.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.reverse.iter.ops"> [lib.reverse.iter.ops]</a>.
</p>
<p><i>[
Copenhagen: The LWG is concerned that the proposed resolution
introduces new overloads. Experience shows that introducing
overloads is always risky, and that it would be inappropriate to
make this change without implementation experience. It may be
desirable to provide this feature in a different way.
]</i></p>
<hr>
<a name="290"><h3>290.&nbsp;Requirements to for_each and its function object</h3></a><p><b>Section:</b>&nbsp;25.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.foreach"> [lib.alg.foreach]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Angelika Langer&nbsp; <b>Date:</b>&nbsp;03 Jan 2001</p>
<p>The specification of the for_each algorithm does not have a
"Requires" section, which means that there are no
restrictions imposed on the function object whatsoever. In essence it
means that I can provide any function object with arbitrary side
effects and I can still expect a predictable result. In particular I
can expect that the function object is applied exactly last - first
times, which is promised in the "Complexity" section.
</p>
<p>I don't see how any implementation can give such a guarantee
without imposing requirements on the function object.
</p>
<p>Just as an example: consider a function object that removes
elements from the input sequence. In that case, what does the
complexity guarantee (applies f exactly last - first times) mean?
</p>
<p>One can argue that this is obviously a nonsensical application and
a theoretical case, which unfortunately it isn't. I have seen
programmers shooting themselves in the foot this way, and they did not
understand that there are restrictions even if the description of the
algorithm does not say so.
</p>
<p><b>Proposed resolution:</b></p>
<p>Add a "Requires" section to section 25.1.1 similar to those
proposed for transform and the numeric algorithms (see issue
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#242">242</a>):
</p>
<blockquote>
-2- <b>Requires</b>: In the range [first, last], f shall not invalidate
iterators or subranges.
</blockquote>
<p><i>[Copenhagen: The LWG agrees that a function object passed to an
algorithm should not invalidate iterators in the range that the
algorithm is operating on. The LWG believes that this should be a
blanket statement in Clause 25, not just a special requirement for
<tt>for_each</tt>.
]</i></p>
<hr>
<a name="294"><h3>294.&nbsp;User defined macros and standard headers</h3></a><p><b>Section:</b>&nbsp;17.4.3.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.macro.names"> [lib.macro.names]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;James Kanze&nbsp; <b>Date:</b>&nbsp;11 Jan 2001</p>
<p>Paragraph 2 of 17.4.3.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.macro.names"> [lib.macro.names]</a> reads: "A
translation unit that includes a header shall not contain any macros
that define names declared in that header." As I read this, it
would mean that the following program is legal:</p>
<pre> #define npos 3.14
#include &lt;sstream&gt;
</pre>
<p>since npos is not defined in &lt;sstream&gt;. It is, however, defined
in &lt;string&gt;, and it is hard to imagine an implementation in
which &lt;sstream&gt; didn't include &lt;string&gt;.</p>
<p>I think that this phrase was probably formulated before it was
decided that a standard header may freely include other standard
headers. The phrase would be perfectly appropriate for C, for
example. In light of 17.4.4.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.res.on.headers"> [lib.res.on.headers]</a> paragraph 1, however,
it isn't stringent enough.</p>
<p><b>Proposed resolution:</b></p>
<p>In paragraph 2 of 17.4.3.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.macro.names"> [lib.macro.names]</a>, change "A
translation unit that includes a header shall not contain any macros
that define names declared in that header." to "A
translation unit that includes a header shall not contain any macros
that define names declared in any standard header."</p>
<p><i>[Copenhagen: the general idea is clearly correct, but there is
concern about making sure that the two paragraphs in 17.4.3.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.macro.names"> [lib.macro.names]</a> remain consistent. Nathan will provide new
wording.]</i></p>
<hr>
<a name="299"><h3>299.&nbsp;Incorrect return types for iterator dereference</h3></a><p><b>Section:</b>&nbsp;24.1.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.bidirectional.iterators"> [lib.bidirectional.iterators]</a>, 24.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.random.access.iterators"> [lib.random.access.iterators]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;John Potter&nbsp; <b>Date:</b>&nbsp;22 Jan 2001</p>
<p>
In section 24.1.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.bidirectional.iterators"> [lib.bidirectional.iterators]</a>,
Table 75 gives the return type of *r-- as convertible to T. This is
not consistent with Table 74 which gives the return type of *r++ as
T&amp;. *r++ = t is valid while *r-- = t is invalid.
</p>
<p>
In section 24.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.random.access.iterators"> [lib.random.access.iterators]</a>,
Table 76 gives the return type of a[n] as convertible to T. This is
not consistent with the semantics of *(a + n) which returns T&amp; by
Table 74. *(a + n) = t is valid while a[n] = t is invalid.
</p>
<p>
Discussion from the Copenhagen meeting: the first part is
uncontroversial. The second part, operator[] for Random Access
Iterators, requires more thought. There are reasonable arguments on
both sides. Return by value from operator[] enables some potentially
useful iterators, e.g. a random access "iota iterator" (a.k.a
"counting iterator" or "int iterator"). There isn't any obvious way
to do this with return-by-reference, since the reference would be to a
temporary. On the other hand, <tt>reverse_iterator</tt> takes an
arbitrary Random Access Iterator as template argument, and its
operator[] returns by reference. If we decided that the return type
in Table 76 was correct, we would have to change
<tt>reverse_iterator</tt>. This change would probably affect user
code.
</p>
<p>
History: the contradiction between <tt>reverse_iterator</tt> and the
Random Access Iterator requirements has been present from an early
stage. In both the STL proposal adopted by the committee
(N0527==94-0140) and the STL technical report (HPL-95-11 (R.1), by
Stepanov and Lee), the Random Access Iterator requirements say that
operator[]'s return value is "convertible to T". In N0527
reverse_iterator's operator[] returns by value, but in HPL-95-11
(R.1), and in the STL implementation that HP released to the public,
reverse_iterator's operator[] returns by reference. In 1995, the
standard was amended to reflect the contents of HPL-95-11 (R.1). The
original intent for operator[] is unclear.
</p>
<p>
In the long term it may be desirable to add more fine-grained
iterator requirements, so that access method and traversal strategy
can be decoupled. (See "Improved Iterator Categories and
Requirements", N1297 = 01-0011, by Jeremy Siek.) Any decisions
about issue 299 should keep this possibility in mind.
</p>
<p>Further discussion: I propose a compromise between John Potter's
resolution, which requires <tt>T&amp;</tt> as the return type of
<tt>a[n]</tt>, and the current wording, which requires convertible to
<tt>T</tt>. The compromise is to keep the convertible to <tt>T</tt>
for the return type of the expression <tt>a[n]</tt>, but to also add
<tt>a[n] = t</tt> as a valid expression. This compromise "saves" the
common case uses of random access iterators, while at the same time
allowing iterators such as counting iterator and caching file
iterators to remain random access iterators (iterators where the
lifetime of the object returned by <tt>operator*()</tt> is tied to the
lifetime of the iterator).
</p>
<p>
Note that the compromise resolution necessitates a change to
<tt>reverse_iterator</tt>. It would need to use a proxy to support
<tt>a[n] = t</tt>.
</p>
<p>
Note also there is one kind of mutable random access iterator that
will no longer meet the new requirements. Currently, iterators that
return an r-value from <tt>operator[]</tt> meet the requirements for a
mutable random access iterartor, even though the expression <tt>a[n] =
t</tt> will only modify a temporary that goes away. With this proposed
resolution, <tt>a[n] = t</tt> will be required to have the same
operational semantics as <tt>*(a + n) = t</tt>.
</p>
<p><b>Proposed resolution:</b></p>
<p>
In section 24.1.4 [lib.bidirectdional.iterators], change the return
type in table 75 from "convertible to <tt>T</tt>" to
<tt>T&amp;</tt>.
</p>
<p>
In section 24.1.5 [lib.random.access.iterators], change the
operational semantics for <tt>a[n]</tt> to " the r-value of
<tt>a[n]</tt> is equivalent to the r-value of <tt>*(a +
n)</tt>". Add a new row in the table for the expression <tt>a[n] = t</tt>
with a return type of convertible to <tt>T</tt> and operational semantics of
<tt>*(a + n) = t</tt>.
</p>
<hr>
<a name="309"><h3>309.&nbsp;Does sentry catch exceptions?</h3></a><p><b>Section:</b>&nbsp;27.6 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.iostream.format"> [lib.iostream.format]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;19 Mar 2001</p>
<p>
The descriptions of the constructors of basic_istream&lt;&gt;::sentry
(27.6.1.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.istream::sentry"> [lib.istream::sentry]</a>) and basic_ostream&lt;&gt;::sentry
(27.6.2.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a>) do not explain what the functions do in
case an exception is thrown while they execute. Some current
implementations allow all exceptions to propagate, others catch them
and set ios_base::badbit instead, still others catch some but let
others propagate.
</p>
<p>
The text also mentions that the functions may call setstate(failbit)
(without actually saying on what object, but presumably the stream
argument is meant). That may have been fine for
basic_istream&lt;&gt;::sentry prior to issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#195">195</a>, since
the function performs an input operation which may fail. However,
issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#195">195</a> amends 27.6.1.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.istream::sentry"> [lib.istream::sentry]</a>, p2 to
clarify that the function should actually call setstate(failbit |
eofbit), so the sentence in p3 is redundant or even somewhat
contradictory.
</p>
<p>
The same sentence that appears in 27.6.2.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a>, p3
doesn't seem to be very meaningful for basic_istream&lt;&gt;::sentry
which performs no input. It is actually rather misleading since it
would appear to guide library implementers to calling
setstate(failbit) when os.tie()-&gt;flush(), the only called function,
throws an exception (typically, it's badbit that's set in response to
such an event).
</p>
<p><b>Additional comments from Martin, who isn't comfortable with the
current proposed resolution</b> (see c++std-lib-11530)</p>
<p>
The istream::sentry ctor says nothing about how the function
deals with exemptions (27.6.1.1.2, p1 says that the class is
responsible for doing "exception safe"(*) prefix and suffix
operations but it doesn't explain what level of exception
safety the class promises to provide). The mockup example
of a "typical implementation of the sentry ctor" given in
27.6.1.1.2, p6, removed in ISO/IEC 14882:2003, doesn't show
exception handling, either. Since the ctor is not classified
as a formatted or unformatted input function, the text in
27.6.1.1, p1 through p4 does not apply. All this would seem
to suggest that the sentry ctor should not catch or in any
way handle exceptions thrown from any functions it may call.
Thus, the typical implementation of an istream extractor may
look something like [1].
</p>
<p>
The problem with [1] is that while it correctly sets ios::badbit
if an exception is thrown from one of the functions called from
the sentry ctor, if the sentry ctor reaches EOF while extracting
whitespace from a stream that has eofbit or failbit set in
exceptions(), it will cause an ios::failure to be thrown, which
will in turn cause the extractor to set ios::badbit.
</p>
<p>
The only straightforward way to prevent this behavior is to
move the definition of the sentry object in the extractor
above the try block (as suggested by the example in 22.2.8,
p9 and also indirectly supported by 27.6.1.3, p1). See [2].
But such an implementation will allow exceptions thrown from
functions called from the ctor to freely propagate to the
caller regardless of the setting of ios::badbit in the stream
object's exceptions().
</p>
<p>
So since neither [1] nor [2] behaves as expected, the only
possible solution is to have the sentry ctor catch exceptions
thrown from called functions, set badbit, and propagate those
exceptions if badbit is also set in exceptions(). (Another
solution exists that deals with both kinds of sentries, but
the code is non-obvious and cumbersome -- see [3].)
</p>
<p>
Please note that, as the issue points out, current libraries
do not behave consistently, suggesting that implementors are
not quite clear on the exception handling in istream::sentry,
despite the fact that some LWG members might feel otherwise.
(As documented by the parenthetical comment here:
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1480.html#309)
</p>
<p>
Also please note that those LWG members who in Copenhagen
felt that "a sentry's constructor should not catch exceptions,
because sentries should only be used within (un)formatted input
functions and that exception handling is the responsibility of
those functions, not of the sentries," as noted here
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1310.html#309
would in effect be either arguing for the behavior described
in [1] or for extractors implemented along the lines of [3].
</p>
<p>
The original proposed resolution (Revision 25 of the issues
list) clarifies the role of the sentry ctor WRT exception
handling by making it clear that extractors (both library
or user-defined) should be implemented along the lines of
[2] (as opposed to [1]) and that no exception thrown from
the callees should propagate out of either function unless
badbit is also set in exceptions().
</p>
<p>[1] Extractor that catches exceptions thrown from sentry:</p>
<blockquote>
<pre>struct S { long i; };
istream&amp; operator&gt;&gt; (istream &amp;strm, S &amp;s)
{
ios::iostate err = ios::goodbit;
try {
const istream::sentry guard (strm, false);
if (guard) {
use_facet&lt;num_get&lt;char&gt; &gt;(strm.getloc ())
.get (istreambuf_iterator&lt;char&gt;(strm),
istreambuf_iterator&lt;char&gt;(),
strm, err, s.i);
}
}
catch (...) {
bool rethrow;
try {
strm.setstate (ios::badbit);
rethrow = false;
}
catch (...) {
rethrow = true;
}
if (rethrow)
throw;
}
if (err)
strm.setstate (err);
return strm;
}
</pre>
</blockquote>
<p>[2] Extractor that propagates exceptions thrown from sentry:</p>
<blockquote>
<pre>istream&amp; operator&gt;&gt; (istream &amp;strm, S &amp;s)
{
istream::sentry guard (strm, false);
if (guard) {
ios::iostate err = ios::goodbit;
try {
use_facet&lt;num_get&lt;char&gt; &gt;(strm.getloc ())
.get (istreambuf_iterator&lt;char&gt;(strm),
istreambuf_iterator&lt;char&gt;(),
strm, err, s.i);
}
catch (...) {
bool rethrow;
try {
strm.setstate (ios::badbit);
rethrow = false;
}
catch (...) {
rethrow = true;
}
if (rethrow)
throw;
}
if (err)
strm.setstate (err);
}
return strm;
}
</pre>
</blockquote>
<p>
[3] Extractor that catches exceptions thrown from sentry
but doesn't set badbit if the exception was thrown as a
result of a call to strm.clear().
</p>
<blockquote>
<pre>istream&amp; operator&gt;&gt; (istream &amp;strm, S &amp;s)
{
const ios::iostate state = strm.rdstate ();
const ios::iostate except = strm.exceptions ();
ios::iostate err = std::ios::goodbit;
bool thrown = true;
try {
const istream::sentry guard (strm, false);
thrown = false;
if (guard) {
use_facet&lt;num_get&lt;char&gt; &gt;(strm.getloc ())
.get (istreambuf_iterator&lt;char&gt;(strm),
istreambuf_iterator&lt;char&gt;(),
strm, err, s.i);
}
}
catch (...) {
if (thrown &amp;&amp; state &amp; except)
throw;
try {
strm.setstate (ios::badbit);
thrown = false;
}
catch (...) {
thrown = true;
}
if (thrown)
throw;
}
if (err)
strm.setstate (err);
return strm;
}
</pre>
</blockquote>
<p><b>Proposed resolution:</b></p>
<p>Remove the last sentence of 27.6.1.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.istream::sentry"> [lib.istream::sentry]</a> p5 (but not
the footnote, which should be moved to the preceding sentence).</p>
<p>Remove the last sentence of 27.6.2.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a> p3 (but not
the footnote, which should be moved to the preceding sentence).</p>
<p><b>Rationale:</b></p>
<p>The LWG feels that no clarification of EH policy is necessary: the
standard is precise about which operations sentry's constructor
performs, and about which of those operations can throw. However, the
sentence at the end should be removed because it's redundant.</p>
<hr>
<a name="342"><h3>342.&nbsp;seek and eofbit</h3></a><p><b>Section:</b>&nbsp;27.6.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.istream.unformatted"> [lib.istream.unformatted]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Howard Hinnant&nbsp; <b>Date:</b>&nbsp;09 Oct 201</p>
<p>I think we have a defect.</p>
<p>According to lwg issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#60">60</a> which is now a dr, the
description of seekg in 27.6.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.istream.unformatted"> [lib.istream.unformatted]</a> paragraph 38 now looks
like:</p>
<blockquote>
Behaves as an unformatted input function (as described in 27.6.1.3,
paragraph 1), except that it does not count the number of characters
extracted and does not affect the value returned by subsequent calls to
gcount(). After constructing a sentry object, if fail() != true,
executes rdbuf()­&gt;pubseekpos( pos).
</blockquote>
<p>And according to lwg issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#243">243</a> which is also now a dr,
27.6.1.3, paragraph 1 looks like:</p>
<blockquote>
Each unformatted input function begins execution by constructing an
object of class sentry with the default argument noskipws (second)
argument true. If the sentry object returns true, when converted to a
value of type bool, the function endeavors to obtain the requested
input. Otherwise, if the sentry constructor exits by throwing an
exception or if the sentry object returns false, when converted to a
value of type bool, the function returns without attempting to obtain
any input. In either case the number of extracted characters is set to
0; unformatted input functions taking a character array of non-zero
size as an argument shall also store a null character (using charT())
in the first location of the array. If an exception is thrown during
input then ios::badbit is turned on in *this'ss error state. If
(exception()&amp;badbit)!= 0 then the exception is rethrown. It also counts
the number of characters extracted. If no exception has been thrown it
ends by storing the count in a member object and returning the value
specified. In any event the sentry object is destroyed before leaving
the unformatted input function.
</blockquote>
<p>And finally 27.6.1.1.2/5 says this about sentry:</p>
<blockquote>
If, after any preparation is completed, is.good() is true, ok_ != false
otherwise, ok_ == false.
</blockquote>
<p>
So although the seekg paragraph says that the operation proceeds if
!fail(), the behavior of unformatted functions says the operation
proceeds only if good(). The two statements are contradictory when only
eofbit is set. I don't think the current text is clear which condition
should be respected.
</p>
<p><b>Further discussion from Redmond:</b></p>
<p>PJP: It doesn't seem quite right to say that <tt>seekg</tt> is
"unformatted". That makes specific claims about sentry that
aren't quite appropriate for seeking, which has less fragile failure
modes than actual input. If we do really mean that it's unformatted
input, it should behave the same way as other unformatted input. On
the other hand, "principle of least surprise" is that seeking from EOF
ought to be OK.</p>
<p>Dietmar: nothing should depend on eofbit. Eofbit should only be
examined by the user to determine why something failed.</p>
<p><i>[Taken from c++std-lib-8873, c++std-lib-8874, c++std-lib-8876]</i></p>
<p><b>Proposed resolution:</b></p>
<p><i>[Santa Cruz: On the one hand, it would clearly be silly to seek
to a non-EOF position without resetting eofbit. On the other hand,
having seek clear eofbit explicitly would set a major precedent:
there is currently <i>no</i> place where any of the flags are reset
without the user explicitly asking for them to be. This is the tip
of a general problem, that the various flags are stickier than many
users might expect. Bill, Gaby, and Howard will discuss this issue
and propose a resolution.]</i></p>
<hr>
<a name="356"><h3>356.&nbsp;Meaning of ctype_base::mask enumerators</h3></a><p><b>Section:</b>&nbsp;22.2.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.category.ctype"> [lib.category.ctype]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Matt Austern&nbsp; <b>Date:</b>&nbsp;23 Jan 2002</p>
<p>What should the following program print?</p>
<pre> #include &lt;locale&gt;
#include &lt;iostream&gt;
class my_ctype : public std::ctype&lt;char&gt;
{
typedef std::ctype&lt;char&gt; base;
public:
my_ctype(std::size_t refs = 0) : base(my_table, false, refs)
{
std::copy(base::classic_table(), base::classic_table() + base::table_size,
my_table);
my_table[(unsigned char) '_'] = (base::mask) (base::print | base::space);
}
private:
mask my_table[base::table_size];
};
int main()
{
my_ctype ct;
std::cout &lt;&lt; "isspace: " &lt;&lt; ct.is(std::ctype_base::space, '_') &lt;&lt; " "
&lt;&lt; "isalpha: " &lt;&lt; ct.is(std::ctype_base::alpha, '_') &lt;&lt; std::endl;
}
</pre>
<p>The goal is to create a facet where '_' is treated as whitespace.</p>
<p>On gcc 3.0, this program prints "isspace: 1 isalpha: 0". On
Microsoft C++ it prints "isspace: 1 isalpha: 1".</p>
<p>
I believe that both implementations are legal, and the standard does not
give enough guidance for users to be able to use std::ctype's
protected interface portably.</p>
<p>
The above program assumes that ctype_base::mask enumerators like
<tt>space</tt> and <tt>print</tt> are disjoint, and that the way to
say that a character is both a space and a printing character is to or
those two enumerators together. This is suggested by the "exposition
only" values in 22.2.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.category.ctype"> [lib.category.ctype]</a>, but it is nowhere specified in
normative text. An alternative interpretation is that the more
specific categories subsume the less specific. The above program
gives the results it does on the Microsoft compiler because, on that
compiler, <tt>print</tt> has all the bits set for each specific
printing character class.
</p>
<p>From the point of view of std::ctype's public interface, there's no
important difference between these two techniques. From the point of
view of the protected interface, there is. If I'm defining a facet
that inherits from std::ctype&lt;char&gt;, I'm the one who defines the
value that table()['a'] returns. I need to know what combination of
mask values I should use. This isn't so very esoteric: it's exactly
why std::ctype has a protected interface. If we care about users
being able to write their own ctype facets, we have to give them a
portable way to do it.
</p>
<p>
Related reflector messages:
lib-9224, lib-9226, lib-9229, lib-9270, lib-9272, lib-9273, lib-9274,
lib-9277, lib-9279.
</p>
<p>Issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#339">339</a> is related, but not identical. The
proposed resolution if issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#339">339</a> says that
ctype_base::mask must be a bitmask type. It does not say that the
ctype_base::mask elements are bitmask elements, so it doesn't
directly affect this issue.</p>
<p>More comments from Benjamin Kosnik, who believes that
that C99 compatibility essentially requires what we're
calling option 1 below.</p>
<blockquote>
<pre>I think the C99 standard is clear, that isspace -&gt; !isalpha.
--------
#include &lt;locale&gt;
#include &lt;iostream&gt;
class my_ctype : public std::ctype&lt;char&gt;
{
private:
typedef std::ctype&lt;char&gt; base;
mask my_table[base::table_size];
public:
my_ctype(std::size_t refs = 0) : base(my_table, false, refs)
{
std::copy(base::classic_table(), base::classic_table() + base::table_size,
my_table);
mask both = base::print | base::space;
my_table[static_cast&lt;mask&gt;('_')] = both;
}
};
int main()
{
using namespace std;
my_ctype ct;
cout &lt;&lt; "isspace: " &lt;&lt; ct.is(ctype_base::space, '_') &lt;&lt; endl;
cout &lt;&lt; "isprint: " &lt;&lt; ct.is(ctype_base::print, '_') &lt;&lt; endl;
// ISO C99, isalpha iff upper | lower set, and !space.
// 7.5, p 193
// -&gt; looks like g++ behavior is correct.
// 356 -&gt; bitmask elements are required for ctype_base
// 339 -&gt; bitmask type required for mask
cout &lt;&lt; "isalpha: " &lt;&lt; ct.is(ctype_base::alpha, '_') &lt;&lt; endl;
}
</pre>
</blockquote>
<p><b>Proposed resolution:</b></p>
<p>Informally, we have three choices:</p>
<ol>
<li>Require that the enumerators are disjoint (except for alnum and
graph)</li>
<li>Require that the enumerators are not disjoint, and specify which
of them subsume which others. (e.g. mandate that lower includes alpha
and print)</li>
<li>Explicitly leave this unspecified, which the result that the above
program is not portable.</li>
</ol>
<p>Either of the first two options is just as good from the standpoint
of portability. Either one will require some implementations to
change.</p>
<p><i>[
More discussion is needed. Nobody likes option 3. Options 1 and 2
are both controversial, 2 perhaps less so. Benjamin thinks that
option 1 is required for C99 compatibility.
]</i></p>
<hr>
<a name="362"><h3>362.&nbsp;bind1st/bind2nd type safety</h3></a><p><b>Section:</b>&nbsp;20.3.6.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.bind.1st"> [lib.bind.1st]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Andrew Demkin&nbsp; <b>Date:</b>&nbsp;26 Apr 2002</p>
<p>
The definition of bind1st() (20.3.6.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.bind.1st"> [lib.bind.1st]</a>) can result in
the construction of an unsafe binding between incompatible pointer
types. For example, given a function whose first parameter type is
'pointer to T', it's possible without error to bind an argument of
type 'pointer to U' when U does not derive from T:
</p>
<pre> foo(T*, int);
struct T {};
struct U {};
U u;
int* p;
int* q;
for_each(p, q, bind1st(ptr_fun(foo), &amp;u)); // unsafe binding
</pre>
<p>
The definition of bind1st() includes a functional-style conversion to
map its argument to the expected argument type of the bound function
(see below):
</p>
<pre> typename Operation::first_argument_type(x)
</pre>
<p>
A functional-style conversion (5.2.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/expr.html#expr.type.conv"> [expr.type.conv]</a>) is defined to be
semantically equivalent to an explicit cast expression (5.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/expr.html#expr.cast"> [expr.cast]</a>), which may (according to 5.4, paragraph 5) be interpreted
as a reinterpret_cast, thus masking the error.
</p>
<p>The problem and proposed change also apply to 20.3.6.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.bind.2nd"> [lib.bind.2nd]</a>.</p>
<p><b>Proposed resolution:</b></p>
<p>
The simplest and most localized change to prevent such errors is to
require bind1st() use a static_cast expression rather than the
functional-style conversion; that is, have bind1st() return:
</p>
<pre> binder1st&lt;Operation&gt;( op,
static_cast&lt;typename Operation::first_argument_type&gt;(x)).
</pre>
<p>
A more agressive solution is to change the semantics of
functional-style conversions to not permit a reinterpret_cast. For
contexts that require the semantics of reinterpret_cast, the language
may want to require the use of an explicit cast expression such as
'(T) x' or 'reinterpret_cast&lt;T&gt;(x)' and limit the behavior of
the functional notation to match statically-checked and standard
conversions (as defined by 5.2.9 and 4.10, etc.). Although changing
the semantics of functional-style conversions may seem drastic and
does have language-wide ramifications, it has the benefit of better
unifying the conversion rules for user defined types and built-in
types, which can be especially important for generic template
programming.
</p>
<p><i>[Santa Cruz: it's clear that a function-style cast is
wrong. Maybe a static cast would be better, or maybe no cast at
all. Jeremy will check with the original author of this part
of the Standard and will see what the original intent was.]</i></p>
<hr>
<a name="366"><h3>366.&nbsp;Excessive const-qualification</h3></a><p><b>Section:</b>&nbsp;27 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.input.output"> [lib.input.output]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Walter Brown, Marc Paterno&nbsp; <b>Date:</b>&nbsp;10 May 2002</p>
<p>
The following member functions are declared const, yet return non-const
pointers. We believe they are should be changed, because they allow code
that may surprise the user. See document N1360 for details and
rationale.
</p>
<p><i>[Santa Cruz: the real issue is that we've got const member
functions that return pointers to non-const, and N1360 proposes
replacing them by overloaded pairs. There isn't a consensus about
whether this is a real issue, since we've never said what our
constness policy is for iostreams. N1360 relies on a distinction
between physical constness and logical constness; that distinction, or
those terms, does not appear in the standard.]</i></p>
<p><b>Proposed resolution:</b></p>
<p>In 27.4.4 and 27.4.4.2</p>
<p>Replace</p>
<pre> basic_ostream&lt;charT,traits&gt;* tie() const;
</pre>
<p>with</p>
<pre> basic_ostream&lt;charT,traits&gt;* tie();
const basic_ostream&lt;charT,traits&gt;* tie() const;
</pre>
<p>and replace</p>
<pre> basic_streambuf&lt;charT,traits&gt;* rdbuf() const;
</pre>
<p>with</p>
<pre> basic_streambuf&lt;charT,traits&gt;* rdbuf();
const basic_streambuf&lt;charT,traits&gt;* rdbuf() const;
</pre>
<p>In 27.5.2 and 27.5.2.3.1</p>
<p>Replace</p>
<pre> char_type* eback() const;
</pre>
<p>with</p>
<pre> char_type* eback();
const char_type* eback() const;
</pre>
<p>Replace</p>
<pre> char_type gptr() const;
</pre>
<p>with</p>
<pre> char_type* gptr();
const char_type* gptr() const;
</pre>
<p>Replace</p>
<pre> char_type* egptr() const;
</pre>
<p>with</p>
<pre> char_type* egptr();
const char_type* egptr() const;
</pre>
<p>In 27.5.2 and 27.5.2.3.2</p>
<p>Replace</p>
<pre> char_type* pbase() const;
</pre>
<p>with</p>
<pre> char_type* pbase();
const char_type* pbase() const;
</pre>
<p>Replace</p>
<pre> char_type* pptr() const;
</pre>
<p>with</p>
<pre> char_type* pptr();
const char_type* pptr() const;
</pre>
<p>Replace</p>
<pre> char_type* epptr() const;
</pre>
<p>with</p>
<pre> char_type* epptr();
const char_type* epptr() const;
</pre>
<p>In 27.7.2, 27.7.2.2, 27.7.3 27.7.3.2, 27.7.4, and 27.7.6</p>
<p>Replace</p>
<pre> basic_stringbuf&lt;charT,traits,Allocator&gt;* rdbuf() const;
</pre>
<p>with</p>
<pre> basic_stringbuf&lt;charT,traits,Allocator&gt;* rdbuf();
const basic_stringbuf&lt;charT,traits,Allocator&gt;* rdbuf() const;
</pre>
<p>In 27.8.1.5, 27.8.1.7, 27.8.1.8, 27.8.1.10, 27.8.1.11, and 27.8.1.13</p>
<p>Replace</p>
<pre> basic_filebuf&lt;charT,traits&gt;* rdbuf() const;
</pre>
<p>with</p>
<pre> basic_filebuf&lt;charT,traits&gt;* rdbuf();
const basic_filebuf&lt;charT,traits&gt;* rdbuf() const;
</pre>
<hr>
<a name="368"><h3>368.&nbsp;basic_string::replace has two "Throws" paragraphs</h3></a><p><b>Section:</b>&nbsp;21.3.5.6 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-strings.html#lib.string::replace"> [lib.string::replace]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Beman Dawes&nbsp; <b>Date:</b>&nbsp;3 Jun 2002</p>
<p>
21.3.5.6 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-strings.html#lib.string::replace"> [lib.string::replace]</a> basic_string::replace, second
signature, given in paragraph 1, has two "Throws" paragraphs (3 and
5).
</p>
<p>
In addition, the second "Throws" paragraph (5) includes specification
(beginning with "Otherwise, the function replaces ...") that should be
part of the "Effects" paragraph.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[This is a typo that escalated. It's clear that what's in the
Standard is wrong. It's less clear what the fix ought to be.
Someone who understands string replace well needs to work on
this.]</i></p>
<hr>
<a name="369"><h3>369.&nbsp;io stream objects and static ctors</h3></a><p><b>Section:</b>&nbsp;27.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.iostream.objects"> [lib.iostream.objects]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Ruslan Abdikeev&nbsp; <b>Date:</b>&nbsp;8 Jul 2002</p>
<p>
Is it safe to use standard iostream objects from constructors of
static objects? Are standard iostream objects constructed and are
their associations established at that time?
</p>
<p>Surpisingly enough, Standard does NOT require that.</p>
<p>
27.3/2 [lib.iostream.objects] guarantees that standard iostream
objects are constructed and their associations are established before
the body of main() begins execution. It also refers to ios_base::Init
class as the panacea for constructors of static objects.
</p>
<p>
However, there's nothing in 27.3 [lib.iostream.objects],
in 27.4.2 [lib.ios.base], and in 27.4.2.1.6 [lib.ios::Init],
that would require implementations to allow access to standard
iostream objects from constructors of static objects.
</p>
<p>Details:</p>
<p>Core text refers to some magic object ios_base::Init, which will
be discussed below:</p>
<blockquote>
"The [standard iostream] objects are constructed, and their
associations are established at some time prior to or during
first time an object of class basic_ios&lt;charT,traits&gt;::Init
is constructed, and in any case before the body of main
begins execution." (27.3/2 [lib.iostream.objects])
</blockquote>
<p>
The first <i>non-normative</i> footnote encourages implementations
to initialize standard iostream objects earlier than required.
</p>
<p>However, the second <i>non-normative</i> footnote makes an explicit
and unsupported claim:</p>
<blockquote>
"Constructors and destructors for static objects can access these
[standard iostream] objects to read input from stdin or write output
to stdout or stderr." (27.3/2 footnote 265 [lib.iostream.objects])
</blockquote>
<p>
The only bit of magic is related to that ios_base::Init class. AFAIK,
the rationale behind ios_base::Init was to bring an instance of this
class to each translation unit which #included &lt;iostream&gt; or
related header. Such an inclusion would support the claim of footnote
quoted above, because in order to use some standard iostream object it
is necessary to #include &lt;iostream&gt;.
</p>
<p>
However, while Standard explicitly describes ios_base::Init as
an appropriate class for doing the trick, I failed to found a
mention of an _instance_ of ios_base::Init in Standard.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Redmond: This still isn't precise enough. We need to give
users some guarantees, i.e. "if you do X, then you are guaranteed
that you will see behavior Y." We should guarantee that stream
objects are constructed before a static constructor if (1)
&lt;iostream&gt; is #included before the relevant static object; or
(2) the user explicitly constructs an ios_base::Init object before
calling that constuctor.]</i></p>
<p>Add to [lib.iostream.objects], p2, immediately before the last sentence
of the paragraph, the following two sentences:</p>
<blockquote>
It is implementation-defined whether the header &lt;iostream&gt; defines
an ios_base::Init object or not. If it does not, an implementation
must specify the means of achieving safe access to the standard
objects for input and output during program startup.
</blockquote>
<p><i>[Santa Cruz: The LWG is leaning toward NAD. There isn't any
normative wording saying that the Init scheme will be used, but that
is probably intentional. Implementers use dirty tricks for iostream
initialization, and doing it portably is somewhere between difficult
and impossible. Too much constraint in this area is dangerous, and if
we are to make any changes it would probably be more appropriate
for them to be nonnormative. Summer '04 mid-meeting mailing: Martin
provided wording for resolution and rationale.]</i></p>
<p><b>Rationale:</b></p>
<p>
The original proposed resolution unconditionally required
implementations to define an ios_base::Init object of some
implementation-defined name in the header &lt;iostream&gt;. That's an
overspecification. First, defining the object may be unnecessary
and even detrimental to performance if an implementation can
guarantee that the 8 standard iostream objects will be initialized
before any other user-defined object in a program. Second, there
is no need to require implementations to document the name of the
object.</p>
<p>
The new proposed resolution specifies that implementations may
(but need not) define an ios_base::Init object, while requiring
them to document whether they do or not, and if not, to document
how portable programs achieve safe access to the 8 standard iostream
objects during program startup (3.6)(*). The intent is that if an
implementation documents that &lt;iostream&gt; defines an ios_base::Init
object, it implies that the header must be #included before any
references to the standard iostream objects. Otherwise, if an
implementation does not define an ios_base::Init object in
&lt;iostream&gt; it must either assure and document that the standard
iostream objects are safely accessible at startup, or specify what
a portable program must do to safely access them (e.g., it may
require that a program define an ios_base::Init object before
doing so, or that it call ios::sync_with_stdio(), etc.).
</p>
<p>
(*) Note that the term startup is broader than the term "Constructors
and destructors for static objects" used in Footnote 265 since the
former includes other functions besides constructors and destructors,
including the following example:
</p>
<pre> int foo () { return (std::cout &lt;&lt; "foo()\n").rdstate (); }
int i = foo ();
int main () { return i; }
</pre>
<hr>
<a name="371"><h3>371.&nbsp;Stability of multiset and multimap member functions</h3></a><p><b>Section:</b>&nbsp;23.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Frank Compagner&nbsp; <b>Date:</b>&nbsp;20 Jul 2002</p>
<p>
The requirements for multiset and multimap containers (23.1
[lib.containers.requirements], 23.1.2 [lib.associative.reqmnts],
23.3.2 [lib.multimap] and 23.3.4 [lib.multiset]) make no mention of
the stability of the required (mutating) member functions. It appears
the standard allows these functions to reorder equivalent elements of
the container at will, yet the pervasive red-black tree implementation
appears to provide stable behaviour.
</p>
<p>This is of most concern when considering the behaviour of erase().
A stability requirement would guarantee the correct working of the
following 'idiom' that removes elements based on a certain predicate
function.
</p>
<pre> multimap&lt;int, int&gt; m;
multimap&lt;int, int&gt;::iterator i = m.begin();
while (i != m.end()) {
if (pred(i))
m.erase (i++);
else
++i;
}
</pre>
<p>
Although clause 23.1.2/8 guarantees that i remains a valid iterator
througout this loop, absence of the stability requirement could
potentially result in elements being skipped. This would make
this code incorrect, and, furthermore, means that there is no way
of erasing these elements without iterating first over the entire
container, and second over the elements to be erased. This would
be unfortunate, and have a negative impact on both performance and
code simplicity.
</p>
<p>
If the stability requirement is intended, it should be made explicit
(probably through an extra paragraph in clause 23.1.2).
</p>
<p>
If it turns out stability cannot be guaranteed, i'd argue that a
remark or footnote is called for (also somewhere in clause 23.1.2) to
warn against relying on stable behaviour (as demonstrated by the code
above). If most implementations will display stable behaviour, any
problems emerging on an implementation without stable behaviour will
be hard to track down by users. This would also make the need for an
erase_if() member function that much greater.
</p>
<p>This issue is somewhat related to LWG issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#130">130</a>.</p>
<p><i>[Santa Cruz: More people need to look at this. Much user code
may assume stability. On the other hand, it seems drastic to add a
new requirement now.]</i></p>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="376"><h3>376.&nbsp;basic_streambuf semantics</h3></a><p><b>Section:</b>&nbsp;27.7.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.stringbuf.virtuals"> [lib.stringbuf.virtuals]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Ray Lischner&nbsp; <b>Date:</b>&nbsp;14 Aug 2002</p>
<p>
In Section 27.7.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.stringbuf.virtuals"> [lib.stringbuf.virtuals]</a>, Table 90, the implication is that
the four conditions should be mutually exclusive, but they are not.
The first two cases, as written, are subcases of the third. I think it
would be clearer if the conditions were rewritten as follows:
</p>
<blockquote>
<p>
(which &amp; (ios_base::in|ios_base::out)) == ios_base::in
</p>
<p>
(which &amp; (ios_base::in|ios_base::out)) == ios_base::out
</p>
<p>
(which &amp; (ios_base::in|ios_base::out)) ==
(ios_base::in|ios_base::out)
and way == either ios_base::beg or ios_base::end
</p>
<p>Otherwise</p>
</blockquote>
<p>
As written, it is unclear what should be the result if cases 1 &amp; 2
are true, but case 3 is false, e.g.,
</p>
<blockquote>
seekoff(0, ios_base::cur, ios_base::in | ios_base::out)
</blockquote>
<p><i>[Santa Cruz: The ambiguity seems real. We need to do a survey of
implementations before we decide on a solution.]</i></p>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="382"><h3>382.&nbsp;codecvt do_in/out result</h3></a><p><b>Section:</b>&nbsp;22.2.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.locale.codecvt"> [lib.locale.codecvt]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;30 Aug 2002</p>
<p>
It seems that the descriptions of codecvt do_in() and do_out() leave
sufficient room for interpretation so that two implementations of
codecvt may not work correctly with the same filebuf. Specifically,
the following seems less than adequately specified:
</p>
<ol>
<li>
the conditions under which the functions terminate
</li>
<li>
precisely when the functions return ok
</li>
<li>
precisely when the functions return partial
</li>
<li>
the full set of conditions when the functions return error
</li>
</ol>
<ol>
<li>
22.2.1.5.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.locale.codecvt.virtuals"> [lib.locale.codecvt.virtuals]</a>, p2 says this about the effects of the
function: ...Stops if it encounters a character it cannot
convert... This assumes that there *is* a character to
convert. What happens when there is a sequence that doesn't form a
valid source character, such as an unassigned or invalid UNICODE
character, or a sequence that cannot possibly form a character
(e.g., the sequence "\xc0\xff" in UTF-8)?
</li>
<li>
Table 53 says that the function returns codecvt_base::ok
to indicate that the function(s) "completed the conversion."
Suppose that the source sequence is "\xc0\x80" in UTF-8,
with from pointing to '\xc0' and (from_end==from + 1).
It is not clear whether the return value should be ok
or partial (see below).
</li>
<li>
Table 53 says that the function returns codecvt_base::partial
if "not all source characters converted." With the from pointers
set up the same way as above, it is not clear whether the return
value should be partial or ok (see above).
</li>
<li>
Table 53, in the row describing the meaning of error mistakenly
refers to a "from_type" character, without the symbol from_type
having been defined. Most likely, the word "source" character
is intended, although that is not sufficient. The functions
may also fail when they encounter an invalid source sequence
that cannot possibly form a valid source character (e.g., as
explained in bullet 1 above).
</li>
</ol>
<p>
Finally, the conditions described at the end of 22.2.1.5.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.locale.codecvt.virtuals"> [lib.locale.codecvt.virtuals]</a>, p4 don't seem to be possible:
</p>
<blockquote>
"A return value of partial, if (from_next == from_end),
indicates that either the destination sequence has not
absorbed all the available destination elements, or that
additional source elements are needed before another
destination element can be produced."
</blockquote>
<p>
If the value is partial, it's not clear to me that (from_next
==from_end) could ever hold if there isn't enough room
in the destination buffer. In order for (from_next==from_end) to
hold, all characters in that range must have been successfully
converted (according to 22.2.1.5.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.locale.codecvt.virtuals"> [lib.locale.codecvt.virtuals]</a>, p2) and since there are no
further source characters to convert, no more room in the
destination buffer can be needed.
</p>
<p>
It's also not clear to me that (from_next==from_end) could ever
hold if additional source elements are needed to produce another
destination character (not element as incorrectly stated in the
text). partial is returned if "not all source characters have
been converted" according to Table 53, which also implies that
(from_next==from) does NOT hold.
</p>
<p>
Could it be that the intended qualifying condition was actually
(from_next != from_end), i.e., that the sentence was supposed
to read
</p>
<blockquote>
"A return value of partial, if (from_next != from_end),..."
</blockquote>
<p>
which would make perfect sense, since, as far as I understand it,
partial can only occur if (from_next != from_end)?
</p>
<p><b>Proposed resolution:</b></p>
<p>
To address these issues, I propose that paragraphs 2, 3, and 4
be rewritten as follows. The proposal incorporates the accepted
resolution of lwg issue 19.
</p>
<pre>-2- Effects: Converts characters in the range of source elements
[from, from_end), placing the results in sequential positions
starting at destination to. Converts no more than (from_end ­ from)
source elements, and stores no more than (to_limit ­ to)
destination elements.
Stops if it encounters a sequence of source elements it cannot
convert to a valid destination character. It always leaves the
from_next and to_next pointers pointing one beyond the last
element successfully converted.
[Note: If returns noconv, internT and externT are the same type
and the converted sequence is identical to the input sequence
[from, from_next). to_next is set equal to to, the value of
state is unchanged, and there are no changes to the values in
[to, to_limit). --end note]
-3- Notes: Its operations on state are unspecified.
[Note: This argument can be used, for example, to maintain shift
state, to specify conversion options (such as count only), or to
identify a cache of seek offsets. --end note]
-4- Returns: An enumeration value, as summarized in Table 53:
Table 53 -- do_in/do_out result values
Value Meaning
+---------+----------------------------------------------------+
| ok | successfully completed the conversion of all |
| | complete characters in the source range |
+---------+----------------------------------------------------+
| partial | the characters in the source range would, after |
| | conversion, require space greater than that |
| | available in the destination range |
+---------+----------------------------------------------------+
| error | encountered either a sequence of elements in the |
| | source range forming a valid source character that |
| | could not be converted to a destination character, |
| | or a sequence of elements in the source range that |
| | could not possibly form a valid source character |
+---------+----------------------------------------------------+
| noconv | internT and externT are the same type, and input |
| | sequence is identical to converted sequence |
+---------+----------------------------------------------------+
A return value of partial, i.e., if (from_next != from_end),
indicates that either the destination sequence has not absorbed
all the available destination elements, or that additional
source elements are needed before another destination character
can be produced.
</pre>
<p><i>[Santa Cruz: The LWG agrees that this is an important issue and
that this general direction is probably correct. Dietmar, Howard,
PJP, and Matt will review this wording.]</i></p>
<p><i>[Kona: this isn't quite right. (a) the description of noconv is
too vague, both in the existing standard and in the current proposed
resolution; (b) the description of what noconv means should be
normative; (c) the phrase "partial, i.e. if from_next != from_end"
isn't quite right, because those are two separate cases, it's possible
to get partial either form insufficient input or from insufficient
space in the output buffer. The big problem is that the standard is
written with the assumption of 1-&gt;N conversion in mind, not M-&gt;N.
Bill, Howard, and Martin will provide new wording.
]</i></p>
<hr>
<a name="384"><h3>384.&nbsp;equal_range has unimplementable runtime complexity</h3></a><p><b>Section:</b>&nbsp;25.3.3.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.equal.range"> [lib.equal.range]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Hans Bos&nbsp; <b>Date:</b>&nbsp;18 Oct 2002</p>
<p>
Section 25.3.3.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.equal.range"> [lib.equal.range]</a>
states that at most 2 * log(last - first) + 1
comparisons are allowed for equal_range.
</p>
<p>It is not possible to implement equal_range with these constraints.</p>
<p>In a range of one element as in:</p>
<pre> int x = 1;
equal_range(&amp;x, &amp;x + 1, 1)
</pre>
<p>it is easy to see that at least 2 comparison operations are needed.</p>
<p>For this case at most 2 * log(1) + 1 = 1 comparison is allowed.</p>
<p>I have checked a few libraries and they all use the same (nonconforming)
algorithm for equal_range that has a complexity of</p>
<pre> 2* log(distance(first, last)) + 2.
</pre>
<p>I guess this is the algorithm that the standard assumes for equal_range.</p>
<p>
It is easy to see that 2 * log(distance) + 2 comparisons are enough
since equal range can be implemented with lower_bound and upper_bound
(both log(distance) + 1).
</p>
<p>
I think it is better to require something like 2log(distance) + O(1) (or
even logarithmic as multiset::equal_range).
Then an implementation has more room to optimize for certain cases (e.g.
have log(distance) characteristics when at most match is found in the range
but 2log(distance) + 4 for the worst case).
</p>
<p><i>[Santa Cruz: The issue is real, but of greater scope than just
equal_range: it affects all of the binary search algorithms. What is
the complexity supposed to be for ranges of 0 or 1 elements? What
base are we using for the logarithm? Are these bounds supposed to be
exact, or asymptotic? (If the latter, of course, then none of the
other questions matter.)]</i></p>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="385"><h3>385.&nbsp;Does call by value imply the CopyConstructible requirement?</h3></a><p><b>Section:</b>&nbsp;17 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.library"> [lib.library]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Matt Austern&nbsp; <b>Date:</b>&nbsp;23 Oct 2002</p>
<p>
Many function templates have parameters that are passed by value;
a typical example is <tt>find_if</tt>'s <i>pred</i> parameter in
25.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.find"> [lib.alg.find]</a>. Are the corresponding template parameters
(<tt>Predicate</tt> in this case) implicitly required to be
CopyConstructible, or does that need to be spelled out explicitly?
</p>
<p>
This isn't quite as silly a question as it might seem to be at first
sight. If you call <tt>find_if</tt> in such a way that template
argument deduction applies, then of course you'll get call by value
and you need to provide a copy constructor. If you explicitly provide
the template arguments, however, you can force call by reference by
writing something like <tt>find_if&lt;my_iterator,
my_predicate&amp;&gt;</tt>. The question is whether implementation
are required to accept this, or whether this is ill-formed because
my_predicate&amp; is not CopyConstructible.
</p>
<p>
The scope of this problem, if it is a problem, is unknown. Function
object arguments to generic algorithms in clauses 25 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.algorithms"> [lib.algorithms]</a>
and 26 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-numerics.html#lib.numerics"> [lib.numerics]</a> are obvious examples. A review of the whole
library is necessary.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[
This is really two issues. First, predicates are typically passed by
value but we don't say they must be Copy Constructible. They should
be. Second: is specialization allowed to transform value arguments
into references? References aren't copy constructible, so this should
not be allowed.
]</i></p>
<hr>
<a name="386"><h3>386.&nbsp;Reverse iterator's operator[] has impossible return type</h3></a><p><b>Section:</b>&nbsp;24.4.1.3.11 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.reverse.iter.opindex"> [lib.reverse.iter.opindex]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Matt Austern&nbsp; <b>Date:</b>&nbsp;23 Oct 2002</p>
<p>In 24.4.1.3.11 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.reverse.iter.opindex"> [lib.reverse.iter.opindex]</a>, <tt>reverse_iterator&lt;&gt;::operator[]</tt>
is specified as having a return type of <tt>reverse_iterator::reference</tt>,
which is the same as <tt>iterator_traits&lt;Iterator&gt;::reference</tt>.
(Where <tt>Iterator</tt> is the underlying iterator type.)</p>
<p>The trouble is that <tt>Iterator</tt>'s own operator[] doesn't
necessarily have a return type
of <tt>iterator_traits&lt;Iterator&gt;::reference</tt>. Its
return type is merely required to be convertible
to <tt>Iterator</tt>'s value type. The return type specified for
reverse_iterator's operator[] would thus appear to be impossible.</p>
<p>With the resolution of issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#299">299</a>, the type of
<tt>a[n]</tt> will continue to be required (for random access
iterators) to be convertible to the value type, and also <tt>a[n] =
t</tt> will be a valid expression. Implementations of
<tt>reverse_iterator</tt> will likely need to return a proxy from
<tt>operator[]</tt> to meet these requirements. As mentioned in the
comment from Dave Abrahams, the simplest way to specify that
<tt>reverse_iterator</tt> meet this requirement to just mandate
it and leave the return type of <tt>operator[]</tt> unspecified.</p>
<p><b>Proposed resolution:</b></p>
<p>In 24.4.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.reverse.iter.requirements"> [lib.reverse.iter.requirements]</a> change:</p>
<blockquote>
<pre>reference operator[](difference_type n) const;
</pre>
</blockquote>
<p>to:</p>
<blockquote>
<pre><b><i>unspecified</i></b> operator[](difference_type n) const; // see <font color="red">lib.random.access.iterators</font>
</pre>
</blockquote>
<p><i>[
Comments from Dave Abrahams: IMO we should resolve 386 by just saying
that the return type of reverse_iterator's operator[] is
unspecified, allowing the random access iterator requirements to
impose an appropriate return type. If we accept 299's proposed
resolution (and I think we should), the return type will be
readable and writable, which is about as good as we can do.
]</i></p>
<hr>
<a name="387"><h3>387.&nbsp;std::complex over-encapsulated</h3></a><p><b>Section:</b>&nbsp;26.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-numerics.html#lib.complex.numbers"> [lib.complex.numbers]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Gabriel Dos Reis&nbsp; <b>Date:</b>&nbsp;8 Nov 2002</p>
<p>
The absence of explicit description of std::complex&lt;T&gt; layout
makes it imposible to reuse existing software developed in traditional
languages like Fortran or C with unambigous and commonly accepted
layout assumptions. There ought to be a way for practitioners to
predict with confidence the layout of std::complex&lt;T&gt; whenever T
is a numerical datatype. The absence of ways to access individual
parts of a std::complex&lt;T&gt; object as lvalues unduly promotes
severe pessimizations. For example, the only way to change,
independently, the real and imaginary parts is to write something like
</p>
<pre>complex&lt;T&gt; z;
// ...
// set the real part to r
z = complex&lt;T&gt;(r, z.imag());
// ...
// set the imaginary part to i
z = complex&lt;T&gt;(z.real(), i);
</pre>
<p>
At this point, it seems appropriate to recall that a complex number
is, in effect, just a pair of numbers with no particular invariant to
maintain. Existing practice in numerical computations has it that a
complex number datatype is usually represented by Cartesian
coordinates. Therefore the over-encapsulation put in the specification
of std::complex&lt;&gt; is not justified.
</p>
<p><b>Proposed resolution:</b></p>
<p>Add the following requirements to 26.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-numerics.html#lib.complex.numbers"> [lib.complex.numbers]</a> as 26.2/4:</p>
<blockquote>
<p>If z is an lvalue expression of type cv std::complex&lt;T&gt; then</p>
<ul>
<li>the expression reinterpret_cast&lt;cv T(&amp;)[2]&gt;(z)
is well-formed; and</li>
<li>reinterpret_cast&lt;cvT(&amp;)[2]&gt;(z)[0]designates the
real part of z; and</li>
<li>reinterpret_cast&lt;cvT(&amp;)[2]&gt;(z)[1]designates the
imaginary part of z.</li>
</ul>
<p>
Moreover, if a is an expression of pointer type cv complex&lt;T&gt;*
and the expression a[i] is well-defined for an integer expression
i then:
</p>
<ul>
<li>reinterpret_cast&lt;cvT*&gt;(a)[2+i] designates the real
part of a[i]; and</li>
<li>reinterpret_cast&lt;cv T*&gt;(a)[2+i+1] designates the
imaginary part of a[i].</li>
</ul>
</blockquote>
<p>In the header synopsis in 26.2.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-numerics.html#lib.complex.synopsis"> [lib.complex.synopsis]</a>, replace</p>
<pre> template&lt;class T&gt; T real(const complex&lt;T&gt;&amp;);
template&lt;class T&gt; T imag(const complex&lt;T&gt;&amp;);
</pre>
<p>with</p>
<pre> template&lt;class T&gt; const T&amp; real(const complex&lt;T&gt;&amp;);
template&lt;class T&gt; T&amp; real( complex&lt;T&gt;&amp;);
template&lt;class T&gt; const T&amp; imag(const complex&lt;T&gt;&amp;);
template&lt;class T&gt; T&amp; imag( complex&lt;T&gt;&amp;);
</pre>
<p>In 26.2.7 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-numerics.html#lib.complex.value.ops"> [lib.complex.value.ops]</a> paragraph 1, change</p>
<pre> template&lt;class T&gt; T real(const complex&lt;T&gt;&amp;);
</pre>
<p>to</p>
<pre> template&lt;class T&gt; const T&amp; real(const complex&lt;T&gt;&amp;);
template&lt;class T&gt; T&amp; real( complex&lt;T&gt;&amp;);
</pre>
<p>and change the <b>Returns</b> clause to "<b>Returns:</b> The real
part of <i>x</i></p>.
<p>In 26.2.7 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-numerics.html#lib.complex.value.ops"> [lib.complex.value.ops]</a> paragraph 2, change</p>
<pre> template&lt;class T&gt; T imag(const complex&lt;T&gt;&amp;);
</pre>
<p>to</p>
<pre> template&lt;class T&gt; const T&amp; imag(const complex&lt;T&gt;&amp;);
template&lt;class T&gt; T&amp; imag( complex&lt;T&gt;&amp;);
</pre>
<p>and change the <b>Returns</b> clause to "<b>Returns:</b> The imaginary
part of <i>x</i></p>.
<p><i>[Kona: The layout guarantee is absolutely necessary for C
compatibility. However, there was disagreement about the other part
of this proposal: retrieving elements of the complex number as
lvalues. An alternative: continue to have real() and imag() return
rvalues, but add set_real() and set_imag(). Straw poll: return
lvalues - 2, add setter functions - 5. Related issue: do we want
reinterpret_cast as the interface for converting a complex to an
array of two reals, or do we want to provide a more explicit way of
doing it? Howard will try to resolve this issue for the next
meeting.]</i></p>
<p><i>[pre-Sydney: Howard summarized the options in n1589.]</i></p>
<p><b>Rationale:</b></p>
<p>The LWG believes that C99 compatibility would be enough
justification for this change even without other considerations. All
existing implementations already have the layout proposed here.</p>
<hr>
<a name="394"><h3>394.&nbsp;behavior of formatted output on failure</h3></a><p><b>Section:</b>&nbsp;27.6.2.5.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ostream.formatted.reqmts"> [lib.ostream.formatted.reqmts]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;27 Dec 2002</p>
<p>
There is a contradiction in Formatted output about what bit is
supposed to be set if the formatting fails. On sentence says it's
badbit and another that it's failbit.
</p>
<p>
27.6.2.5.1, p1 says in the Common Requirements on Formatted output
functions:
</p><pre> ... If the generation fails, then the formatted output function
does setstate(ios::failbit), which might throw an exception.
</pre>
<p></p>
<p>
27.6.2.5.2, p1 goes on to say this about Arithmetic Inserters:
</p>
<p>
... The formatting conversion occurs as if it performed the
following code fragment:
</p>
<p>
</p><pre> bool failed =
use_facet&lt;num_put&lt;charT,ostreambuf_iterator&lt;charT,traits&gt;
&gt; &gt;
(getloc()).put(*this, *this, fill(), val). failed();
... If failed is true then does setstate(badbit) ...
</pre>
<p></p>
<p>
The original intent of the text, according to Jerry Schwarz (see
c++std-lib-10500), is captured in the following paragraph:
</p>
<p>
In general "badbit" should mean that the stream is unusable because
of some underlying failure, such as disk full or socket closure;
"failbit" should mean that the requested formatting wasn't possible
because of some inconsistency such as negative widths. So typically
if you clear badbit and try to output something else you'll fail
again, but if you clear failbit and try to output something else
you'll succeed.
</p>
<p>
In the case of the arithmetic inserters, since num_put cannot
report failure by any means other than exceptions (in response
to which the stream must set badbit, which prevents the kind of
recoverable error reporting mentioned above), the only other
detectable failure is if the iterator returned from num_put
returns true from failed().
</p>
<p>
Since that can only happen (at least with the required iostream
specializations) under such conditions as the underlying failure
referred to above (e.g., disk full), setting badbit would seem
to be the appropriate response (indeed, it is required in
27.6.2.5.2, p1). It follows that failbit can never be directly
set by the arithmetic (it can only be set by the sentry object
under some unspecified conditions).
</p>
<p>
The situation is different for other formatted output functions
which can fail as a result of the streambuf functions failing
(they may do so by means other than exceptions), and which are
then required to set failbit.
</p>
<p>
The contradiction, then, is that ostream::operator&lt;&lt;(int) will
set badbit if the disk is full, while operator&lt;&lt;(ostream&amp;,
char) will set failbit under the same conditions. To make the behavior
consistent, the Common requirements sections for the Formatted output
functions should be changed as proposed below.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Kona: There's agreement that this is a real issue. What we
decided at Kona: 1. An error from the buffer (which can be detected
either directly from streambuf's member functions or by examining a
streambuf_iterator) should always result in badbit getting set.
2. There should never be a circumstance where failbit gets set.
That represents a formatting error, and there are no circumstances
under which the output facets are specified as signaling a
formatting error. (Even more so for string output that for numeric
because there's nothing to format.) If we ever decide to make it
possible for formatting errors to exist then the facets can signal
the error directly, and that should go in clause 22, not clause 27.
3. The phrase "if generation fails" is unclear and should be
eliminated. It's not clear whether it's intended to mean a buffer
error (e.g. a full disk), a formatting error, or something else.
Most people thought it was supposed to refer to buffer errors; if
so, we should say so. Martin will provide wording.]</i></p>
<p><b>Rationale:</b></p>
<hr>
<a name="396"><h3>396.&nbsp;what are characters zero and one</h3></a><p><b>Section:</b>&nbsp;23.3.5.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.bitset.cons"> [lib.bitset.cons]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;5 Jan 2003</p>
<p>
23.3.5.1, p6 [lib.bitset.cons] talks about a generic character
having the value of 0 or 1 but there is no definition of what
that means for charT other than char and wchar_t. And even for
those two types, the values 0 and 1 are not actually what is
intended -- the values '0' and '1' are. This, along with the
converse problem in the description of to_string() in 23.3.5.2,
p33, looks like a defect remotely related to DR 303.
</p>
<p>
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#303
</p>
<pre>23.3.5.1:
-6- An element of the constructed string has value zero if the
corresponding character in str, beginning at position pos,
is 0. Otherwise, the element has the value one.
</pre>
<pre>23.3.5.2:
-33- Effects: Constructs a string object of the appropriate
type and initializes it to a string of length N characters.
Each character is determined by the value of its
corresponding bit position in *this. Character position N
?- 1 corresponds to bit position zero. Subsequent decreasing
character positions correspond to increasing bit positions.
Bit value zero becomes the character 0, bit value one becomes
the character 1.
</pre>
<p>
Also note the typo in 23.3.5.1, p6: the object under construction
is a bitset, not a string.
</p>
<p><b>Proposed resolution:</b></p>
<p>Change the constructor's function declaration immediately before
23.3.5.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.bitset.cons"> [lib.bitset.cons]</a> p3 to:</p>
<pre> template &lt;class charT, class traits, class Allocator&gt;
explicit
bitset(const basic_string&lt;charT, traits, Allocator&gt;&amp; str,
typename basic_string&lt;charT, traits, Allocator&gt;::size_type pos = 0,
typename basic_string&lt;charT, traits, Allocator&gt;::size_type n =
basic_string&lt;charT, traits, Allocator&gt;::npos,
charT zero = charT('0'), charT one = charT('1'))
</pre>
<p>Change the first two sentences of 23.3.5.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.bitset.cons"> [lib.bitset.cons]</a> p6 to: "An
element of the constructed string has value 0 if the corresponding
character in <i>str</i>, beginning at position <i>pos</i>,
is <i>zero</i>. Otherwise, the element has the value 1.</p>
<p>Change the text of the second sentence in 23.3.5.1, p5 to read:
"The function then throws invalid_argument if any of the rlen
characters in str beginning at position pos is other than <i>zero</i>
or <i>one</i>. The function uses traits::eq() to compare the character
values."
</p>
<p>Change the declaration of the <tt>to_string</tt> member function
immediately before 23.3.5.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.bitset.members"> [lib.bitset.members]</a> p33 to:</p>
<pre> template &lt;class charT, class traits, class Allocator&gt;
basic_string&lt;charT, traits, Allocator&gt;
to_string(charT zero = charT('0'), charT one = charT('1')) const;
</pre>
<p>Change the last sentence of 23.3.5.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.bitset.members"> [lib.bitset.members]</a> p33 to: "Bit
value 0 becomes the character <tt><i>zero</i></tt>, bit value 1 becomes the
character <tt><i>one</i></tt>.</p>
<p>Change 23.3.5.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.bitset.operators"> [lib.bitset.operators]</a> p8 to:</p>
<p><b>Returns</b>:</p>
<pre> os &lt;&lt; x.template to_string&lt;charT,traits,allocator&lt;charT&gt; &gt;(
use_facet&lt;ctype&lt;charT&gt; &gt;(<i>os</i>.getloc()).widen('0'),
use_facet&lt;ctype&lt;charT&gt; &gt;(<i>os</i>.getloc()).widen('1'));
</pre>
<p><b>Rationale:</b></p>
<p>There is a real problem here: we need the character values of '0'
and '1', and we have no way to get them since strings don't have
imbued locales. In principle the "right" solution would be to
provide an extra object, either a ctype facet or a full locale,
which would be used to widen '0' and '1'. However, there was some
discomfort about using such a heavyweight mechanism. The proposed
resolution allows those users who care about this issue to get it
right.</p>
<p>We fix the inserter to use the new arguments. Note that we already
fixed the analogous problem with the extractor in issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#303">303</a>.</p>
<hr>
<a name="397"><h3>397.&nbsp;ostream::sentry dtor throws exceptions</h3></a><p><b>Section:</b>&nbsp;27.6.2.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;5 Jan 2003</p>
<p>
17.4.4.8, p3 prohibits library dtors from throwing exceptions.
</p>
<p>
27.6.2.3, p4 says this about the ostream::sentry dtor:
</p>
<pre> -4- If ((os.flags() &amp; ios_base::unitbuf) &amp;&amp; !uncaught_exception())
is true, calls os.flush().
</pre>
<p>
27.6.2.6, p7 that describes ostream::flush() says:
</p>
<pre> -7- If rdbuf() is not a null pointer, calls rdbuf()-&gt;pubsync().
If that function returns ?-1 calls setstate(badbit) (which
may throw ios_base::failure (27.4.4.3)).
</pre>
<p>
That seems like a defect, since both pubsync() and setstate() can
throw an exception.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[
The contradiction is real. Clause 17 says destructors may never
throw exceptions, and clause 27 specifies a destructor that does
throw. In principle we might change either one. We're leaning
toward changing clause 17: putting in an "unless otherwise specified"
clause, and then putting in a footnote saying the sentry destructor
is the only one that can throw. PJP suggests specifying that
sentry::~sentry() should internally catch any exceptions it might cause.
]</i></p>
<hr>
<a name="398"><h3>398.&nbsp;effects of end-of-file on unformatted input functions</h3></a><p><b>Section:</b>&nbsp;27.6.2.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;5 Jan 2003</p>
<p>
While reviewing unformatted input member functions of istream
for their behavior when they encounter end-of-file during input
I found that the requirements vary, sometimes unexpectedly, and
in more than one case even contradict established practice (GNU
libstdc++ 3.2, IBM VAC++ 6.0, STLPort 4.5, SunPro 5.3, HP aCC
5.38, Rogue Wave libstd 3.1, and Classic Iostreams).
</p>
<p>
The following unformatted input member functions set eofbit if they
encounter an end-of-file (this is the expected behavior, and also
the behavior of all major implementations):
</p>
<p>
</p><pre> basic_istream&lt;charT, traits&gt;&amp;
get (char_type*, streamsize, char_type);
</pre>
<p></p>
<p>
Also sets failbit if it fails to extract any characters.
</p>
<p>
</p><pre> basic_istream&lt;charT, traits&gt;&amp;
get (char_type*, streamsize);
</pre>
<p></p>
<p>
Also sets failbit if it fails to extract any characters.
</p>
<p>
</p><pre> basic_istream&lt;charT, traits&gt;&amp;
getline (char_type*, streamsize, char_type);
</pre>
<p></p>
<p>
Also sets failbit if it fails to extract any characters.
</p>
<p>
</p><pre> basic_istream&lt;charT, traits&gt;&amp;
getline (char_type*, streamsize);
</pre>
<p></p>
<p>
Also sets failbit if it fails to extract any characters.
</p>
<p>
</p><pre> basic_istream&lt;charT, traits&gt;&amp;
ignore (int, int_type);
</pre>
<p></p>
<p>
</p><pre> basic_istream&lt;charT, traits&gt;&amp;
read (char_type*, streamsize);
</pre>
<p></p>
<p>
Also sets failbit if it encounters end-of-file.
</p>
<p>
</p><pre> streamsize readsome (char_type*, streamsize);
</pre>
<p></p>
<p>
The following unformated input member functions set failbit but
not eofbit if they encounter an end-of-file (I find this odd
since the functions make it impossible to distinguish a general
failure from a failure due to end-of-file; the requirement is
also in conflict with all major implementation which set both
eofbit and failbit):
</p>
<p>
</p><pre> int_type get();
</pre>
<p></p>
<p>
</p><pre> basic_istream&lt;charT, traits&gt;&amp;
get (char_type&amp;);
</pre>
<p></p>
<p>
These functions only set failbit of they extract no characters,
otherwise they don't set any bits, even on failure (I find this
inconsistency quite unexpected; the requirement is also in
conflict with all major implementations which set eofbit
whenever they encounter end-of-file):
</p>
<p>
</p><pre> basic_istream&lt;charT, traits&gt;&amp;
get (basic_streambuf&lt;charT, traits&gt;&amp;, char_type);
</pre>
<p></p>
<p>
</p><pre> basic_istream&lt;charT, traits&gt;&amp;
get (basic_streambuf&lt;charT, traits&gt;&amp;);
</pre>
<p></p>
<p>
This function sets no bits (all implementations except for
STLport and Classic Iostreams set eofbit when they encounter
end-of-file):
</p>
<p>
</p><pre> int_type peek ();
</pre>
<p></p>
<p><b>Proposed resolution:</b></p>
<p>Informally, what we want is a global statement of intent saying
that eofbit gets set if we trip across EOF, and then we can take
away the specific wording for individual functions. A full review
is necessary. The wording currently in the standard is a mishmash,
and changing it on an individual basis wouldn't make things better.
Dietmar will do this work.</p>
<hr>
<a name="401"><h3>401.&nbsp; incorrect type casts in table 32 in lib.allocator.requirements</h3></a><p><b>Section:</b>&nbsp;20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Markus Mauhart&nbsp; <b>Date:</b>&nbsp;27 Feb 2003</p>
<p>
I think that in par2 of 20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a> the last two
lines of table 32 contain two incorrect type casts. The lines are ...
</p>
<pre> a.construct(p,t) Effect: new((void*)p) T(t)
a.destroy(p) Effect: ((T*)p)?-&gt;~T()
</pre>
<p>
.... with the prerequisits coming from the preceding two paragraphs, especially
from table 31:
</p>
<pre> alloc&lt;T&gt; a ;// an allocator for T
alloc&lt;T&gt;::pointer p ;// random access iterator
// (may be different from T*)
alloc&lt;T&gt;::reference r = *p;// T&amp;
T const&amp; t ;
</pre>
<p>
For that two type casts ("(void*)p" and "(T*)p") to be well-formed
this would require then conversions to T* and void* for all
alloc&lt;T&gt;::pointer, so it would implicitely introduce extra
requirements for alloc&lt;T&gt;::pointer, additionally to the only
current requirement (being a random access iterator).
</p>
<p><b>Proposed resolution:</b></p>
<p>
"(void*)p" should be replaced with "(void*)&amp;*p" and that
"((T*)p)?-&gt;" should be replaced with "(*p)." or with
"(&amp;*p)-&gt;".
</p>
<p>
Note: Actually I would prefer to replace "((T*)p)?-&gt;dtor_name" with
"p?-&gt;dtor_name", but AFAICS this is not possible cause of an omission
in 13.5.6 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/over.html#over.ref"> [over.ref]</a> (for which I have filed another DR on 29.11.2002).
</p>
<p><i>[Kona: The LWG thinks this is somewhere on the border between
Open and NAD. The intend is clear: <tt>construct</tt> constructs an
object at the location <i>p</i>. It's reading too much into the
description to think that literally calling <tt>new</tt> is
required. Tweaking this description is low priority until we can do
a thorough review of allocators, and, in particular, allocators with
non-default pointer types.]</i></p>
<hr>
<a name="406"><h3>406.&nbsp;vector::insert(s) exception safety</h3></a><p><b>Section:</b>&nbsp;23.2.4.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.modifiers"> [lib.vector.modifiers]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Dave Abrahams&nbsp; <b>Date:</b>&nbsp;27 Apr 2003</p>
<p>
There is a possible defect in the standard: the standard text was
never intended to prevent arbitrary ForwardIterators, whose operations
may throw exceptions, from being passed, and it also wasn't intended
to require a temporary buffer in the case where ForwardIterators were
passed (and I think most implementations don't use one). As is, the
standard appears to impose requirements that aren't met by any
existing implementation.
</p>
<p><b>Proposed resolution:</b></p>
<p>Replace 23.2.4.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.modifiers"> [lib.vector.modifiers]</a> paragraph 1 with:</p>
<blockquote>
1- Notes: Causes reallocation if the new size is greater than the
old capacity. If no reallocation happens, all the iterators and
references before the insertion point remain valid. If an exception
is thrown other than by the copy constructor or assignment operator
of T or by any InputIterator operation there are no effects.
</blockquote>
<p><i>[We probably need to say something similar for deque.]</i></p>
<hr>
<a name="408"><h3>408.&nbsp;Is vector&lt;reverse_iterator&lt;char*&gt; &gt; forbidden?</h3></a><p><b>Section:</b>&nbsp;24.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Nathan Myers&nbsp; <b>Date:</b>&nbsp;3 June 2003</p>
<p>
I've been discussing iterator semantics with Dave Abrahams, and a
surprise has popped up. I don't think this has been discussed before.
</p>
<p>
24.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a> says that the only operation that can be performed on "singular"
iterator values is to assign a non-singular value to them. (It
doesn't say they can be destroyed, and that's probably a defect.)
Some implementations have taken this to imply that there is no need
to initialize the data member of a reverse_iterator&lt;&gt; in the default
constructor. As a result, code like
</p>
<blockquote>
std::vector&lt;std::reverse_iterator&lt;char*&gt; &gt; v(7);
v.reserve(1000);
</blockquote>
<p>
invokes undefined behavior, because it must default-initialize the
vector elements, and then copy them to other storage. Of course many
other vector operations on these adapters are also left undefined,
and which those are is not reliably deducible from the standard.
</p>
<p>
I don't think that 24.1 was meant to make standard-library iterator
types unsafe. Rather, it was meant to restrict what operations may
be performed by functions which take general user- and standard
iterators as arguments, so that raw pointers would qualify as
iterators. However, this is not clear in the text, others have come
to the opposite conclusion.
</p>
<p>
One question is whether the standard iterator adaptors have defined
copy semantics. Another is whether they have defined destructor
semantics: is
</p>
<blockquote>
{ std::vector&lt;std::reverse_iterator&lt;char*&gt; &gt; v(7); }
</blockquote>
<p>
undefined too?
</p>
<p>
Note this is not a question of whether algorithms are allowed to
rely on copy semantics for arbitrary iterators, just whether the
types we actually supply support those operations. I believe the
resolution must be expressed in terms of the semantics of the
adapter's argument type. It should make clear that, e.g., the
reverse_iterator&lt;T&gt; constructor is actually required to execute
T(), and so copying is defined if the result of T() is copyable.
</p>
<p>
Issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#235">235</a>, which defines reverse_iterator's default
constructor more precisely, has some relevance to this issue.
However, it is not the whole story.
</p>
<p>
The issue was whether
</p>
<blockquote>
reverse_iterator() { }
</blockquote>
<p>
is allowed, vs.
</p>
<blockquote>
reverse_iterator() : current() { }
</blockquote>
<p>
The difference is when T is char*, where the first leaves the member
uninitialized, and possibly equal to an existing pointer value, or
(on some targets) may result in a hardware trap when copied.
</p>
<p>
8.5 paragraph 5 seems to make clear that the second is required to
satisfy DR <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#235">235</a>, at least for non-class Iterator argument
types.
</p>
<p>
But that only takes care of reverse_iterator, and doesn't establish
a policy for all iterators. (The reverse iterator adapter was just
an example.) In particular, does my function
</p>
<blockquote>
template &lt;typename Iterator&gt;
void f() { std::vector&lt;Iterator&gt; v(7); }
</blockquote>
<p>
evoke undefined behavior for some conforming iterator definitions?
I think it does, now, because vector&lt;&gt; will destroy those singular
iterator values, and that's explicitly disallowed.
</p>
<p>
24.1 shouldn't give blanket permission to copy all singular iterators,
because then pointers wouldn't qualify as iterators. However, it
should allow copying of that subset of singular iterator values that
are default-initialized, and it should explicitly allow destroying any
iterator value, singular or not, default-initialized or not.
</p>
<p>Related issue: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#407">407</a></p>
<p><b>Proposed resolution:</b></p>
<p><i>[
We don't want to require all singular iterators to be copyable,
because that is not the case for pointers. However, default
construction may be a special case. Issue: is it really default
construction we want to talk about, or is it something like value
initialization? We need to check with core to see whether default
constructed pointers are required to be copyable; if not, it would be
wrong to impose so strict a requirement for iterators.
]</i></p>
<hr>
<a name="409"><h3>409.&nbsp;Closing an fstream should clear error state</h3></a><p><b>Section:</b>&nbsp;27.8.1.7 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ifstream.members"> [lib.ifstream.members]</a>, 27.8.1.10 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ofstream.members"> [lib.ofstream.members]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Nathan Myers&nbsp; <b>Date:</b>&nbsp;3 June 2003</p>
<p>
A strict reading of 27.8.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.fstreams"> [lib.fstreams]</a> shows that opening or
closing a basic_[io]fstream does not affect the error bits. This
means, for example, that if you read through a file up to EOF, and
then close the stream and reopen it at the beginning of the file,
the EOF bit in the stream's error state is still set. This is
counterintuitive.
</p>
<p>
The LWG considered this issue once before, as issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#22">22</a>,
and put in a footnote to clarify that the strict reading was indeed
correct. We did that because we believed the standard was
unambiguous and consistent, and that we should not make architectural
changes in a TC. Now that we're working on a new revision of the
language, those considerations no longer apply.
</p>
<p><b>Proposed resolution:</b></p>
<p>Change 27.8.1.7 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ifstream.members"> [lib.ifstream.members]</a>, para. 3 from:</p>
<blockquote>
Calls rdbuf()-&gt;open(s,mode|in). If that function returns a null
pointer, calls setstate(failbit) (which may throw ios_base::failure
[Footnote: (lib.iostate.flags)].
</blockquote>
<p>to:</p>
<blockquote>Calls rdbuf()-&gt;open(s,mode|in). If that function returns
a null pointer, calls setstate(failbit) (which may throw
ios_base::failure [Footnote: (lib.iostate.flags)), else calls clear().
</blockquote>
<p>Change 27.8.1.10 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ofstream.members"> [lib.ofstream.members]</a>, para. 3 from:</p>
<blockquote>Calls rdbuf()-&gt;open(s,mode|out). If that function
returns a null pointer, calls setstate(failbit) (which may throw
ios_base::failure [Footnote: (lib.iostate.flags)).
</blockquote>
<p>to:</p>
<blockquote>Calls rdbuf()-&gt;open(s,mode|out). If that function
returns a null pointer, calls setstate(failbit) (which may throw
ios_base::failure [Footnote: (lib.iostate.flags)), else calls clear().
</blockquote>
<p>Change 27.8.1.13 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.fstream.members"> [lib.fstream.members]</a>, para. 3 from:</p>
<blockquote>Calls rdbuf()-&gt;open(s,mode), If that function returns a
null pointer, calls setstate(failbit), (which may throw
ios_base::failure). (lib.iostate.flags) )
</blockquote>
<p>to:</p>
<blockquote>Calls rdbuf()-&gt;open(s,mode), If that function returns a
null pointer, calls setstate(failbit), (which may throw
ios_base::failure). (lib.iostate.flags) ), else calls clear().
</blockquote>
<p><i>[Kona: the LWG agrees this is a good idea. Post-Kona: Bill
provided wording. He suggests having open, not close, clear the error
flags.]</i></p>
<p><i>[Post-Sydney: Howard provided a new proposed resolution. The
old one didn't make sense because it proposed to fix this at the
level of basic_filebuf, which doesn't have access to the stream's
error state. Howard's proposed resolution fixes this at the level
of the three fstream class template instead.]</i></p>
<hr>
<a name="413"><h3>413.&nbsp;Proposed resolution to LDR#64 still wrong</h3></a><p><b>Section:</b>&nbsp;27.6.1.2.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.istream::extractors"> [lib.istream::extractors]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Bo Persson&nbsp; <b>Date:</b>&nbsp;13 Jul 2003</p>
<p>
The second sentence of the proposed resolution says:
</p>
<p>
"If it inserted no characters because it caught an exception thrown
while extracting characters from sb and ..."
</p>
<p>
However, we are not extracting from sb, but extracting from the
basic_istream (*this) and inserting into sb. I can't really tell if
"extracting" or "sb" is a typo.
</p>
<p><i>[
Sydney: Definitely a real issue. We are, indeed, extracting characters
from an istream and not from sb. The problem was there in the FDIS and
wasn't fixed by issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#64">64</a>. Probably what was intended was
to have *this instead of sb. We're talking about the exception flag
state of a basic_istream object, and there's only one basic_istream
object in this discussion, so that would be a consistent
interpretation. (But we need to be careful: the exception policy of
this member function must be consistent with that of other
extractors.) PJP will provide wording.
]</i></p>
<p><b>Proposed resolution:</b></p>
<p>Change the sentence from:</p>
<blockquote>
If it inserted no characters because it caught an exception thrown
while extracting characters from sb and failbit is on in exceptions(),
then the caught exception is rethrown.
</blockquote>
<p>to:</p>
<blockquote>
If it inserted no characters because it caught an exception thrown
while extracting characters from *this and failbit is on in exceptions(),
then the caught exception is rethrown.
</blockquote>
<hr>
<a name="416"><h3>416.&nbsp;definitions of XXX_MIN and XXX_MAX macros in climits</h3></a><p><b>Section:</b>&nbsp;18.2.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-support.html#lib.c.limits"> [lib.c.limits]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
Given two overloads of the function foo(), one taking an argument of type
int and the other taking a long, which one will the call foo(LONG_MAX)
resolve to? The expected answer should be foo(long), but whether that
is true depends on the #defintion of the LONG_MAX macro, specifically
its type. This issue is about the fact that the type of these macros
is not actually required to be the same as the the type each respective
limit.
<br>
Section 18.2.2 of the C++ Standard does not specify the exact types of
the XXX_MIN and XXX_MAX macros #defined in the &lt;climits&gt; and &lt;limits.h&gt;
headers such as INT_MAX and LONG_MAX and instead defers to the C standard.
<br>
Section 5.2.4.2.1, p1 of the C standard specifies that "The values [of
these constants] shall be replaced by constant expressions suitable for use
in #if preprocessing directives. Moreover, except for CHAR_BIT and MB_LEN_MAX,
the following shall be replaced by expressions that have the same type as
would an expression that is an object of the corresponding type converted
according to the integer promotions."
<br>
The "corresponding type converted according to the integer promotions" for
LONG_MAX is, according to 6.4.4.1, p5 of the C standard, the type of long
converted to the first of the following set of types that can represent it:
int, long int, long long int. So on an implementation where (sizeof(long)
== sizeof(int)) this type is actually int, while on an implementation where
(sizeof(long) &gt; sizeof(int)) holds this type will be long.
<br>
This is not an issue in C since the type of the macro cannot be detected
by any conforming C program, but it presents a portability problem in C++
where the actual type is easily detectable by overload resolution.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Kona: the LWG does not believe this is a defect. The C macro
definitions are what they are; we've got a better
mechanism, <tt>std::numeric_limits</tt>, that is specified more
precisely than the C limit macros. At most we should add a
nonnormative note recommending that users who care about the exact
types of limit quantities should use &lt;limits&gt; instead of
&lt;climits&gt;.]</i></p>
<hr>
<a name="417"><h3>417.&nbsp;what does ctype::do_widen() return on failure</h3></a><p><b>Section:</b>&nbsp;22.2.1.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.locale.ctype.virtuals"> [lib.locale.ctype.virtuals]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
The Effects and Returns clauses of the do_widen() member function of
the ctype facet fail to specify the behavior of the function on failure.
That the function may not be able to simply cast the narrow character
argument to the type of the result since doing so may yield the wrong value
for some wchar_t encodings. Popular implementations of ctype&lt;wchar_t&gt; that
use mbtowc() and UTF-8 as the native encoding (e.g., GNU glibc) will fail
when the argument's MSB is set. There is no way for the the rest of locale
and iostream to reliably detect this failure.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Kona: This is a real problem. Widening can fail. It's unclear
what the solution should be. Returning WEOF works for the wchar_t
specialization, but not in general. One option might be to add a
default, like <i>narrow</i>. But that's an incompatible change.
Using <i>traits::eof</i> might seem like a good idea, but facets
don't have access to traits (a recurring problem). We could
have <i>widen</i> throw an exception, but that's a scary option;
existing library components aren't written with the assumption
that <i>widen</i> can throw.]</i></p>
<hr>
<a name="418"><h3>418.&nbsp;exceptions thrown during iostream cleanup</h3></a><p><b>Section:</b>&nbsp;27.4.2.1.6 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ios::Init"> [lib.ios::Init]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
The dtor of the ios_base::Init object is supposed to call flush() on the
6 standard iostream objects cout, cerr, clog, wcout, wcerr, and wclog.
This call may cause an exception to be thrown.
</p>
<p>
17.4.4.8, p3 prohibits all library destructors from throwing exceptions.
</p>
<p>
The question is: What should this dtor do if one or more of these calls
to flush() ends up throwing an exception? This can happen quite easily
if one of the facets installed in the locale imbued in the iostream
object throws.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Kona: We probably can't do much better than what we've got, so
the LWG is leaning toward NAD. At the point where the standard
stream objects are being cleaned up, the usual error reporting
mechanism are all unavailable. And exception from flush at this
point will definitely cause problems. A quality implementation
might reasonably swallow the exception, or call abort, or do
something even more drastic.]</i></p>
<hr>
<a name="419"><h3>419.&nbsp;istream extractors not setting failbit if eofbit is already set</h3></a><p><b>Section:</b>&nbsp;27.6.1.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.istream::sentry"> [lib.istream::sentry]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
27.6.1.1.2, p2 says that istream::sentry ctor prepares for input if is.good()
is true. p4 then goes on to say that the ctor sets the sentry::ok_ member to
true if the stream state is good after any preparation. 27.6.1.2.1, p1 then
says that a formatted input function endeavors to obtain the requested input
if the sentry's operator bool() returns true.
Given these requirements, no formatted extractor should ever set failbit if
the initial stream rdstate() == eofbit. That is contrary to the behavior of
all implementations I tested. The program below prints out
eof = 1, fail = 0
eof = 1, fail = 1
on all of them.
</p>
<pre>
#include &lt;sstream&gt;
#include &lt;cstdio&gt;
int main()
{
std::istringstream strm ("1");
int i = 0;
strm &gt;&gt; i;
std::printf ("eof = %d, fail = %d\n",
!!strm.eof (), !!strm.fail ());
strm &gt;&gt; i;
std::printf ("eof = %d, fail = %d\n",
!!strm.eof (), !!strm.fail ());
}
</pre>
<p>
<br>
Comments from Jerry Schwarz (c++std-lib-11373):
<br>
Jerry Schwarz wrote:
<br>
I don't know where (if anywhere) it says it in the standard, but the
formatted extractors are supposed to set failbit if they don't extract
any characters. If they didn't then simple loops like
<br>
while (cin &gt;&gt; x);
<br>
would loop forever.
<br>
Further comments from Martin Sebor:
<br>
The question is which part of the extraction should prevent this from happening
by setting failbit when eofbit is already set. It could either be the sentry
object or the extractor. It seems that most implementations have chosen to
set failbit in the sentry [...] so that's the text that will need to be
corrected.
</p>
<p><b>Proposed resolution:</b></p>
<p>Kona: Possibly NAD. If eofbit is set then good() will return false. We
then set <i>ok</i> to false. We believe that the sentry's
constructor should always set failbit when <i>ok</i> is false, and
we also think the standard already says that. Possibly it could be
clearer.</p>
<hr>
<a name="421"><h3>421.&nbsp;is basic_streambuf copy-constructible?</h3></a><p><b>Section:</b>&nbsp;27.5.2.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.streambuf.cons"> [lib.streambuf.cons]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
The reflector thread starting with c++std-lib-11346 notes that the class
template basic_streambuf, along with basic_stringbuf and basic_filebuf,
is copy-constructible but that the semantics of the copy constructors
are not defined anywhere. Further, different implementations behave
differently in this respect: some prevent copy construction of objects
of these types by declaring their copy ctors and assignment operators
private, others exhibit undefined behavior, while others still give
these operations well-defined semantics.
</p>
<p>
Note that this problem doesn't seem to be isolated to just the three
types mentioned above. A number of other types in the library section
of the standard provide a compiler-generated copy ctor and assignment
operator yet fail to specify their semantics. It's believed that the
only types for which this is actually a problem (i.e. types where the
compiler-generated default may be inappropriate and may not have been
intended) are locale facets. See issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#439">439</a>.
</p>
<p><b>Proposed resolution:</b></p>
<p>
27.5.2 [lib.streambuf]: Add into the synopsis, public section, just above the destructor declaration:
</p>
<blockquote>
<pre>basic_streambuf(const basic_streambuf&amp; sb);
basic_streambuf&amp; operator=(const basic_streambuf&amp; sb);
</pre>
</blockquote>
<p>Insert after 27.5.2.1, paragraph 2:</p>
<blockquote>
<pre>basic_streambuf(const basic_streambuf&amp; sb);
</pre>
<p>Constructs a copy of sb.</p>
<p>Postcondtions:</p>
<pre> eback() == sb.eback()
gptr() == sb.gptr()
egptr() == sb.egptr()
pbase() == sb.pbase()
pptr() == sb.pptr()
epptr() == sb.epptr()
getloc() == sb.getloc()
</pre>
<pre>basic_streambuf&amp; operator=(const basic_streambuf&amp; sb);
</pre>
<p>Assigns the data members of sb to this.</p>
<p>Postcondtions:</p>
<pre> eback() == sb.eback()
gptr() == sb.gptr()
egptr() == sb.egptr()
pbase() == sb.pbase()
pptr() == sb.pptr()
epptr() == sb.epptr()
getloc() == sb.getloc()
</pre>
<p>Returns: *this.</p>
</blockquote>
<p>27.7.1 [lib.stringbuf]:</p>
<b>Option A:</b>
<blockquote>
<p>Insert into the basic_stringbuf synopsis in the private section:</p>
<pre>basic_stringbuf(const basic_stringbuf&amp;); // not defined
basic_stringbuf&amp; operator=(const basic_stringbuf&amp;); // not defined
</pre>
</blockquote>
<b>Option B:</b>
<blockquote>
<p>Insert into the basic_stringbuf synopsis in the public section:</p>
<pre>basic_stringbuf(const basic_stringbuf&amp; sb);
basic_stringbuf&amp; operator=(const basic_stringbuf&amp; sb);
</pre>
<p>27.7.1.1, insert after paragraph 4:</p>
<pre>basic_stringbuf(const basic_stringbuf&amp; sb);</pre>
<p>
Constructs an independent copy of sb as if with sb.str(), and with the openmode that sb was constructed with.
</p>
<p>Postcondtions: </p>
<pre> str() == sb.str()
gptr() - eback() == sb.gptr() - sb.eback()
egptr() - eback() == sb.egptr() - sb.eback()
pptr() - pbase() == sb.pptr() - sb.pbase()
getloc() == sb.getloc()
</pre>
<p>Note: The only requirement on epptr() is that it point beyond the
initialized range if an output sequence exists. There is no requirement
that epptr() - pbase() == sb.epptr() - sb.pbase().
</p>
<pre>basic_stringbuf&amp; operator=(const basic_stringbuf&amp; sb);</pre>
<p>After assignment the basic_stringbuf has the same state as if it
were initially copy constructed from sb, except that the
basic_stringbuf is allowed to retain any excess capacity it might have,
which may in turn effect the value of epptr().
</p>
</blockquote>
<p>27.8.1.1 [lib.filebuf]</p>
<p>Insert at the bottom of the basic_filebuf synopsis:</p>
<blockquote>
<pre>private:
basic_filebuf(const basic_filebuf&amp;); // not defined
basic_filebuf&amp; operator=(const basic_filebuf&amp;); // not defined
</pre>
</blockquote>
<p><i>[Kona: this is an issue for basic_streambuf itself and for its
derived classes. We are leaning toward allowing basic_streambuf to
be copyable, and specifying its precise semantics. (Probably the
obvious: copying the buffer pointers.) We are less sure whether
the streambuf derived classes should be copyable. Howard will
write up a proposal.]</i></p>
<p><i>[Sydney: Dietmar presented a new argument against basic_streambuf
being copyable: it can lead to an encapsulation violation. Filebuf
inherits from streambuf. Now suppose you inhert a my_hijacking_buf
from streambuf. You can copy the streambuf portion of a filebuf to a
my_hijacking_buf, giving you access to the pointers into the
filebuf's internal buffer. Perhaps not a very strong argument, but
it was strong enough to make people nervous. There was weak
preference for having streambuf not be copyable. There was weak
preference for having stringbuf not be copyable even if streambuf
is. Move this issue to open for now.
]</i></p>
<p><b>Rationale:</b></p>
<p>
27.5.2 [lib.streambuf]: The proposed basic_streambuf copy constructor
and assignment operator are the same as currently implied by the lack
of declarations: public and simply copies the data members. This
resolution is not a change but a clarification of the current
standard.
</p>
<p>
27.7.1 [lib.stringbuf]: There are two reasonable options: A) Make
basic_stringbuf not copyable. This is likely the status-quo of
current implementations. B) Reasonable copy semantics of
basic_stringbuf can be defined and implemented. A copyable
basic_streambuf is arguably more useful than a non-copyable one. This
should be considered as new functionality and not the fixing of a
defect. If option B is chosen, ramifications from issue 432 are taken
into account.
</p>
<p>
27.8.1.1 [lib.filebuf]: There are no reasonable copy semantics for
basic_filebuf.
</p>
<hr>
<a name="422"><h3>422.&nbsp;explicit specializations of member functions of class templates</h3></a><p><b>Section:</b>&nbsp;17.4.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.reserved.names"> [lib.reserved.names]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
It has been suggested that 17.4.3.1, p1 may or may not allow programs to
explicitly specialize members of standard templates on user-defined types.
The answer to the question might have an impact where library requirements
are given using the "as if" rule. I.e., if programs are allowed to specialize
member functions they will be able to detect an implementation's strict
conformance to Effects clauses that describe the behavior of the function
in terms of the other member function (the one explicitly specialized by
the program) by relying on the "as if" rule.
</p>
<p><b>Proposed resolution:</b></p>
<p>
Add the following sentence immediately after the text of 17.4.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.reserved.names"> [lib.reserved.names]</a>, p1:
</p>
<blockquote>
The behavior of a program that declares explicit specializations
of any members of class templates or explicit specializations of
any member templates of classes or class templates defined in
this library is undefined.
</blockquote>
<p><i>[Kona: straw poll was 6-1 that user programs should not be
allowed to specialize individual member functions of standard
library class templates, and that doing so invokes undefined
behavior. Post-Kona: Martin provided wording.]</i></p>
<p><i>[Sydney: The LWG agrees that the standard shouldn't permit users
to specialize individual member functions unless they specialize the
whole class, but we're not sure these words say what we want them to;
they could be read as prohibiting the specialization of any standard
library class templates. We need to consult with CWG to make sure we
use the right wording.]</i></p>
<hr>
<a name="423"><h3>423.&nbsp;effects of negative streamsize in iostreams</h3></a><p><b>Section:</b>&nbsp;27 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.input.output"> [lib.input.output]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
A third party test suite tries to exercise istream::ignore(N) with
a negative value of N and expects that the implementation will treat
N as if it were 0. Our implementation asserts that (N &gt;= 0) holds and
aborts the test.
</p>
<p>
I can't find anything in section 27 that prohibits such values but I don't
see what the effects of such calls should be, either (this applies to
a number of unformatted input functions as well as some member functions
of the basic_streambuf template).
</p>
<p><b>Proposed resolution:</b></p>
<p>
I propose that we add to each function in clause 27 that takes an argument,
say N, of type streamsize a Requires clause saying that "N &gt;= 0." The intent
is to allow negative streamsize values in calls to precision() and width()
but disallow it in calls to streambuf::sgetn(), istream::ignore(), or
ostream::write().
</p>
<p><i>[Kona: The LWG agreed that this is probably what we want. However, we
need a review to find all places where functions in clause 27 take
arguments of type streamsize that shouldn't be allowed to go
negative. Martin will do that review.]</i></p>
<hr>
<a name="424"><h3>424.&nbsp;normative notes</h3></a><p><b>Section:</b>&nbsp;17.3.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.structure.summary"> [lib.structure.summary]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
The text in 17.3.1.1, p1 says:
<br>
"Paragraphs labelled "Note(s):" or "Example(s):" are informative, other
paragraphs are normative."
<br>
The library section makes heavy use of paragraphs labeled "Notes(s),"
some of which are clearly intended to be normative (see list 1), while
some others are not (see list 2). There are also those where the intent
is not so clear (see list 3).
<br>
List 1 -- Examples of (presumably) normative Notes:
<br>
20.4.1.1, p3, 20.4.1.1, p10, 21.3.1, p11, 22.1.1.2, p11, 23.2.1.3, p2,
25.3.7, p3, 26.2.6, p14a, 27.5.2.4.3, p7.
<br>
List 2 -- Examples of (presumably) informative Notes:
<br>
18.4.1.3, p3, 21.3.5.6, p14, 22.2.1.5.2, p3, 25.1.1, p4, 26.2.5, p1,
27.4.2.5, p6.
<br>
List 3 -- Examples of Notes that are not clearly either normative
or informative:
<br>
22.1.1.2, p8, 22.1.1.5, p6, 27.5.2.4.5, p4.
<br>
None of these lists is meant to be exhaustive.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Definitely a real problem. The big problem is there's material
that doesn't quite fit any of the named paragraph categories
(e.g. <b>Effects</b>). Either we need a new kind of named
paragraph, or we need to put more material in unnamed paragraphs
jsut after the signature. We need to talk to the Project Editor
about how to do this.
]</i></p>
<hr>
<a name="427"><h3>427.&nbsp;stage 2 and rationale of DR 221</h3></a><p><b>Section:</b>&nbsp;22.2.2.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.facet.num.get.virtuals"> [lib.facet.num.get.virtuals]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
The requirements specified in Stage 2 and reiterated in the rationale
of DR 221 (and echoed again in DR 303) specify that num_get&lt;charT&gt;::
do_get() compares characters on the stream against the widened elements
of "012...abc...ABCX+-"
</p>
<p>
An implementation is required to allow programs to instantiate the num_get
template on any charT that satisfies the requirements on a user-defined
character type. These requirements do not include the ability of the
character type to be equality comparable (the char_traits template must
be used to perform tests for equality). Hence, the num_get template cannot
be implemented to support any arbitrary character type. The num_get template
must either make the assumption that the character type is equality-comparable
(as some popular implementations do), or it may use char_traits&lt;charT&gt; to do
the comparisons (some other popular implementations do that). This diversity
of approaches makes it difficult to write portable programs that attempt to
instantiate the num_get template on user-defined types.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Kona: the heart of the problem is that we're theoretically
supposed to use traits classes for all fundamental character
operations like assignment and comparison, but facets don't have
traits parameters. This is a fundamental design flaw and it
appears all over the place, not just in this one place. It's not
clear what the correct solution is, but a thorough review of facets
and traits is in order. The LWG considered and rejected the
possibility of changing numeric facets to use narrowing instead of
widening. This may be a good idea for other reasons (see issue
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#459">459</a>), but it doesn't solve the problem raised by this
issue. Whether we use widen or narrow the <tt>num_get</tt> facet
still has no idea which traits class the user wants to use for
the comparison, because only streams, not facets, are passed traits
classes. The standard does not require that two different
traits classes with the same <tt>char_type</tt> must necessarily
have the same behavior.]</i></p>
<p>Informally, one possibility: require that some of the basic
character operations, such as <tt>eq</tt>, <tt>lt</tt>,
and <tt>assign</tt>, must behave the same way for all traits classes
with the same <tt>char_type</tt>. If we accept that limitation on
traits classes, then the facet could reasonably be required to
use <tt>char_traits&lt;charT&gt;</tt></p>.
<hr>
<a name="430"><h3>430.&nbsp;valarray subset operations</h3></a><p><b>Section:</b>&nbsp;26.3.2.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-numerics.html#lib.valarray.sub"> [lib.valarray.sub]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;18 Sep 2003</p>
<p>
The standard fails to specify the behavior of valarray::operator[](slice)
and other valarray subset operations when they are passed an "invalid"
slice object, i.e., either a slice that doesn't make sense at all (e.g.,
slice (0, 1, 0) or one that doesn't specify a valid subset of the valarray
object (e.g., slice (2, 1, 1) for a valarray of size 1).
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Kona: the LWG believes that invalid slices should invoke
undefined behavior. Valarrays are supposed to be designed for high
performance, so we don't want to require specific checking. We
need wording to express this decision.]</i></p>
<hr>
<a name="431"><h3>431.&nbsp;Swapping containers with unequal allocators</h3></a><p><b>Section:</b>&nbsp;20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a>, 25 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.algorithms"> [lib.algorithms]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Matt Austern&nbsp; <b>Date:</b>&nbsp;20 Sep 2003</p>
<p>Clause 20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a> paragraph 4 says that implementations
are permitted to supply containers that are unable to cope with
allocator instances and that container implementations may assume
that all instances of an allocator type compare equal. We gave
implementers this latitude as a temporary hack, and eventually we
want to get rid of it. What happens when we're dealing with
allocators that <i>don't</i> compare equal?
</p>
<p>In particular: suppose that <tt>v1</tt> and <tt>v2</tt> are both
objects of type <tt>vector&lt;int, my_alloc&gt;</tt> and that
<tt>v1.get_allocator() != v2.get_allocator()</tt>. What happens if
we write <tt>v1.swap(v2)</tt>? Informally, three possibilities:</p>
<p>1. This operation is illegal. Perhaps we could say that an
implementation is required to check and to throw an exception, or
perhaps we could say it's undefined behavior.</p>
<p>2. The operation performs a slow swap (i.e. using three
invocations of <tt>operator=</tt>, leaving each allocator with its
original container. This would be an O(N) operation.</p>
<p>3. The operation swaps both the vectors' contents and their
allocators. This would be an O(1) operation. That is:</p>
<blockquote>
<pre> my_alloc a1(...);
my_alloc a2(...);
assert(a1 != a2);
vector&lt;int, my_alloc&gt; v1(a1);
vector&lt;int, my_alloc&gt; v2(a2);
assert(a1 == v1.get_allocator());
assert(a2 == v2.get_allocator());
v1.swap(v2);
assert(a1 == v2.get_allocator());
assert(a2 == v1.get_allocator());
</pre>
</blockquote>
<p><b>Proposed resolution:</b></p>
<p><i>[Kona: This is part of a general problem. We need a paper
saying how to deal with unequal allocators in general.]</i></p>
<p><i>[pre-Sydney: Howard argues for option 3 in n1599.]</i></p>
<hr>
<a name="434"><h3>434.&nbsp;bitset::to_string() hard to use</h3></a><p><b>Section:</b>&nbsp;23.3.5.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.bitset.members"> [lib.bitset.members]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;15 Oct 2003</p>
<p>
It has been pointed out a number of times that the bitset to_string() member
function template is tedious to use since callers must explicitly specify the
entire template argument list (3 arguments). At least two implementations
provide a number of overloads of this template to make it easier to use.
</p>
<p><b>Proposed resolution:</b></p>
<p>In order to allow callers to specify no template arguments at all, just the
first one (charT), or the first 2 (charT and traits), in addition to all
three template arguments, add the following three overloads to both the
interface (declarations only) of the class template bitset as well as to
section 23.3.5.2, immediately after p34, the Returns clause of the existing
to_string() member function template:</p>
<pre> template &lt;class charT, class traits&gt;
basic_string&lt;charT, traits, allocator&lt;charT&gt; &gt;
to_string () const;
-34.1- Returns: to_string&lt;charT, traits, allocator&lt;charT&gt; &gt;().
template &lt;class charT&gt;
basic_string&lt;charT, char_traits&lt;charT&gt;, allocator&lt;charT&gt; &gt;
to_string () const;
-34.2- Returns: to_string&lt;charT, char_traits&lt;charT&gt;, allocator&lt;charT&gt; &gt;().
basic_string&lt;char, char_traits&lt;char&gt;, allocator&lt;char&gt; &gt;
to_string () const;
-34.3- Returns: to_string&lt;char, char_traits&lt;char&gt;, allocator&lt;char&gt; &gt;().
</pre>
<p><i>[Kona: the LWG agrees that this is an improvement over the
status quo. Dietmar thought about an alternative using a proxy
object but now believes that the proposed resolution above is the
right choice.
]</i></p>
<hr>
<a name="438"><h3>438.&nbsp;Ambiguity in the "do the right thing" clause</h3></a><p><b>Section:</b>&nbsp;23.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.sequence.reqmts"> [lib.sequence.reqmts]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Howard Hinnant&nbsp; <b>Date:</b>&nbsp;20 Oct 2003</p>
<p>Section 23.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.sequence.reqmts"> [lib.sequence.reqmts]</a>, paragraphs 9-11, fixed up the problem
noticed with statements like:</p>
<pre>vector&lt;int&gt; v(10, 1);
</pre>
<p>The intent of the above statement was to construct with:</p>
<pre>vector(size_type, const value_type&amp;);
</pre>
<p>but early implementations failed to compile as they bound to:</p>
<pre>template &lt;class InputIterator&gt;
vector(InputIterator f, InputIterator l);
</pre>
<p>instead.</p>
<p>Paragraphs 9-11 say that if InputIterator is an integral type, then the
member template constructor will have the same effect as:</p>
<pre>vector&lt;static_cast&lt;size_type&gt;(f), static_cast&lt;value_type&gt;(l));
</pre>
<p>(and similarly for the other member template functions of sequences).</p>
<p>There is also a note that describes one implementation technique:</p>
<blockquote>
One way that sequence implementors can satisfy this requirement is to
specialize the member template for every integral type.
</blockquote>
<p>This might look something like:</p>
<blockquote>
<pre>template &lt;class T&gt;
struct vector
{
typedef unsigned size_type;
explicit vector(size_type) {}
vector(size_type, const T&amp;) {}
template &lt;class I&gt;
vector(I, I);
// ...
};
template &lt;class T&gt;
template &lt;class I&gt;
vector&lt;T&gt;::vector(I, I) { ... }
template &lt;&gt;
template &lt;&gt;
vector&lt;int&gt;::vector(int, int) { ... }
template &lt;&gt;
template &lt;&gt;
vector&lt;int&gt;::vector(unsigned, unsigned) { ... }
// ...
</pre>
</blockquote>
<p>Label this solution 'A'.</p>
<p>The standard also says:</p>
<blockquote>
Less cumbersome implementation techniques also exist.
</blockquote>
<p>
A popular technique is to not specialize as above, but instead catch
every call with the member template, detect the type of InputIterator,
and then redirect to the correct logic. Something like:
</p>
<blockquote>
<pre>template &lt;class T&gt;
template &lt;class I&gt;
vector&lt;T&gt;::vector(I f, I l)
{
choose_init(f, l, int2type&lt;is_integral&lt;I&gt;::value&gt;());
}
template &lt;class T&gt;
template &lt;class I&gt;
vector&lt;T&gt;::choose_init(I f, I l, int2type&lt;false&gt;)
{
// construct with iterators
}
template &lt;class T&gt;
template &lt;class I&gt;
vector&lt;T&gt;::choose_init(I f, I l, int2type&lt;true&gt;)
{
size_type sz = static_cast&lt;size_type&gt;(f);
value_type v = static_cast&lt;value_type&gt;(l);
// construct with sz,v
}
</pre>
</blockquote>
<p>Label this solution 'B'.</p>
<p>Both of these solutions solve the case the standard specifically
mentions:</p>
<pre>vector&lt;int&gt; v(10, 1); // ok, vector size 10, initialized to 1
</pre>
<p>
However, (and here is the problem), the two solutions have different
behavior in some cases where the value_type of the sequence is not an
integral type. For example consider:
</p>
<blockquote><pre> pair&lt;char, char&gt; p('a', 'b');
vector&lt;vector&lt;pair&lt;char, char&gt; &gt; &gt; d('a', 'b');
</pre></blockquote>
<p>
The second line of this snippet is likely an error. Solution A catches
the error and refuses to compile. The reason is that there is no
specialization of the member template constructor that looks like:
</p>
<pre>template &lt;&gt;
template &lt;&gt;
vector&lt;vector&lt;pair&lt;char, char&gt; &gt; &gt;::vector(char, char) { ... }
</pre>
<p>
So the expression binds to the unspecialized member template
constructor, and then fails (compile time) because char is not an
InputIterator.
</p>
<p>
Solution B compiles the above example though. 'a' is casted to an
unsigned integral type and used to size the outer vector. 'b' is
static casted to the inner vector using it's explicit constructor:
</p>
<pre>explicit vector(size_type n);
</pre>
<p>
and so you end up with a static_cast&lt;size_type&gt;('a') by
static_cast&lt;size_type&gt;('b') matrix.
</p>
<p>
It is certainly possible that this is what the coder intended. But the
explicit qualifier on the inner vector has been thwarted at any rate.
</p>
<p>
The standard is not clear whether the expression:
</p>
<pre> vector&lt;vector&lt;pair&lt;char, char&gt; &gt; &gt; d('a', 'b');
</pre>
<p>
(and similar expressions) are:
</p>
<ol>
<li> undefined behavior.</li>
<li> illegal and must be rejected.</li>
<li> legal and must be accepted.</li>
</ol>
<p>My preference is listed in the order presented.</p>
<p>There are still other techniques for implementing the requirements of
paragraphs 9-11, namely the "restricted template technique" (e.g.
enable_if). This technique is the most compact and easy way of coding
the requirements, and has the behavior of #2 (rejects the above
expression).
</p>
<p>
Choosing 1 would allow all implementation techniques I'm aware of.
Choosing 2 would allow only solution 'A' and the enable_if technique.
Choosing 3 would allow only solution 'B'.
</p>
<p>
Possible wording for a future standard if we wanted to actively reject
the expression above would be to change "static_cast" in paragraphs
9-11 to "implicit_cast" where that is defined by:
</p>
<blockquote>
<pre>template &lt;class T, class U&gt;
inline
T implicit_cast(const U&amp; u)
{
return u;
}
</pre>
</blockquote>
<p><b>Proposed resolution:</b></p>
Replace 23.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.sequence.reqmts"> [lib.sequence.reqmts]</a> paragraphs 9 - 11 with:
<p>For every sequence defined in this clause and in clause lib.strings:</p>
<ul>
<li>
<p>If the constructor</p>
<pre> template &lt;class InputIterator&gt;
X(InputIterator f, InputIterator l,
const allocator_type&amp; a = allocator_type())
</pre>
<p>is called with a type InputIterator that does not qualify as
an input iterator, then the constructor will behave as if the
overloaded constructor:</p>
<pre> X(size_type, const value_type&amp; = value_type(),
const allocator_type&amp; = allocator_type())
</pre>
<p>were called instead, with the arguments static_cast&lt;size_type&gt;(f), l and a, respectively.</p>
</li>
<li>
<p>If the member functions of the forms:</p>
<pre> template &lt;class InputIterator&gt; // such as insert()
rt fx1(iterator p, InputIterator f, InputIterator l);
template &lt;class InputIterator&gt; // such as append(), assign()
rt fx2(InputIterator f, InputIterator l);
template &lt;class InputIterator&gt; // such as replace()
rt fx3(iterator i1, iterator i2, InputIterator f, InputIterator l);
</pre>
<p>are called with a type InputIterator that does not qualify as
an input iterator, then these functions will behave as if the
overloaded member functions:</p>
<pre> rt fx1(iterator, size_type, const value_type&amp;);
rt fx2(size_type, const value_type&amp;);
rt fx3(iterator, iterator, size_type, const value_type&amp;);
</pre>
<p>were called instead, with the same arguments.</p>
</li>
</ul>
<p>In the previous paragraph the alternative binding will fail if f
is not implicitly convertible to X::size_type or if l is not implicitly
convertible to X::value_type.</p>
<p>
The extent to which an implementation determines that a type cannot be
an input iterator is unspecified, except that as a minimum integral
types shall not qualify as input iterators.
</p>
<p><i>[
Kona: agreed that the current standard requires <tt>v('a', 'b')</tt>
to be accepted, and also agreed that this is surprising behavior. The
LWG considered several options, including something like
implicit_cast, which doesn't appear to be quite what we want. We
considered Howards three options: allow acceptance or rejection,
require rejection as a compile time error, and require acceptance. By
straw poll (1-6-1), we chose to require a compile time error.
Post-Kona: Howard provided wording.
]</i></p>
<p><i>[
Sydney: The LWG agreed with this general direction, but there was some
discomfort with the wording in the original proposed resolution.
Howard submitted new wording, and we will review this again in
Redmond.
]</i></p>
<p><i>[Redmond: one very small change in wording: the first argument
is cast to size_t. This fixes the problem of something like
<tt>vector&lt;vector&lt;int&gt; &gt;(5, 5)</tt>, where int is not
implicitly convertible to the value type.]</i></p>
<p><b>Rationale:</b></p>
<p>The proposed resolution fixes:</p>
<pre> vector&lt;int&gt; v(10, 1);
</pre>
<p>
since as integral types 10 and 1 must be disqualified as input
iterators and therefore the (size,value) constructor is called (as
if).</p>
<p>The proposed resolution breaks:</p>
<pre> vector&lt;vector&lt;T&gt; &gt; v(10, 1);
</pre>
<p>
because the integral type 1 is not *implicitly* convertible to
vector&lt;T&gt;. The wording above requires a diagnostic.</p>
<p>
The proposed resolution leaves the behavior of the following code
unspecified.
</p>
<pre> struct A
{
operator int () const {return 10;}
};
struct B
{
B(A) {}
};
vector&lt;B&gt; v(A(), A());
</pre>
<p>
The implementation may or may not detect that A is not an input
iterator and employee the (size,value) constructor. Note though that
in the above example if the B(A) constructor is qualified explicit,
then the implementation must reject the constructor as A is no longer
implicitly convertible to B.
</p>
<hr>
<a name="444"><h3>444.&nbsp;Bad use of casts in fstream</h3></a><p><b>Section:</b>&nbsp;27.8.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.fstreams"> [lib.fstreams]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Vincent Leloup&nbsp; <b>Date:</b>&nbsp;20 Nov 2003</p>
<p>
27.8.1.7 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ifstream.members"> [lib.ifstream.members]</a> p1, 27.8.1.10 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ofstream.members"> [lib.ofstream.members]</a> p1, 27.8.1.13 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.fstream.members"> [lib.fstream.members]</a> p1 seems have same problem as exposed in LWG issue
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#252">252</a>.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Sydney: Genuine defect. 27.8.1.13 needs a cast to cast away
constness. The other two places are stylistic: we could change the
C-style casts to const_cast. Post-Sydney: Howard provided wording.
]</i></p>
<p>Change 27.8.1.7/1 from:</p>
<blockquote>
Returns: (basic_filebuf&lt;charT,traits&gt;*)&amp;sb.
</blockquote>
<p>to:</p>
<blockquote>
Returns: const_cast&lt;basic_filebuf&lt;charT,traits&gt;*&gt;(&amp;sb).
</blockquote>
<p>Change 27.8.1.10/1 from:</p>
<blockquote>
Returns: (basic_filebuf&lt;charT,traits&gt;*)&amp;sb.
</blockquote>
<p>to:</p>
<blockquote>
Returns: const_cast&lt;basic_filebuf&lt;charT,traits&gt;*&gt;(&amp;sb).
</blockquote>
<p>Change 27.8.1.13/1 from:</p>
<blockquote>
Returns: &amp;sb.
</blockquote>
<p>to:</p>
<blockquote>
Returns: const_cast&lt;basic_filebuf&lt;charT,traits&gt;*&gt;(&amp;sb).
</blockquote>
<hr>
<a name="445"><h3>445.&nbsp;iterator_traits::reference unspecified for some iterator categories</h3></a><p><b>Section:</b>&nbsp;24.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.iterator.traits"> [lib.iterator.traits]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Dave Abrahams&nbsp; <b>Date:</b>&nbsp;9 Dec 2003</p>
<p>
The standard places no restrictions at all on the reference type
of input, output, or forward iterators (for forward iterators it
only specifies that *x must be value_type&amp; and doesn't mention
the reference type). Bidirectional iterators' reference type is
restricted only by implication, since the base iterator's
reference type is used as the return type of reverse_iterator's
operator*, which must be T&amp; in order to be a conforming forward
iterator.
</p>
<p>
Here's what I think we ought to be able to expect from an input
or forward iterator's reference type R, where a is an iterator
and V is its value_type
</p>
<ul>
<li>
*a is convertible to R
</li>
<li>
R is convertible to V
</li>
<li>
static_cast&lt;V&gt;(static_cast&lt;R&gt;(*a)) is equivalent to
static_cast&lt;V&gt;(*a)
</li>
</ul>
<p>A mutable forward iterator ought to satisfy, for x of type V:</p>
<li>
{ R r = *a; r = x; } is equivalent to *a = x;
</li>
<p>
I think these requirements capture existing container iterators
(including vector&lt;bool&gt;'s), but render istream_iterator invalid;
its reference type would have to be changed to a constant
reference.
</p>
<p>
(Jeremy Siek) During the discussion in Sydney, it was felt that a
simpler long term solution for this was needed. The solution proposed
was to require <tt>reference</tt> to be the same type as <tt>*a</tt>
and <tt>pointer</tt> to be the same type as <tt>a-&gt;</tt>. Most
iterators in the Standard Library already meet this requirement. Some
iterators are output iterators, and do not need to meet the
requirement, and others are only specified through the general
iterator requirements (which will change with this resolution). The
sole case where there is an explicit definition of the reference type
that will need to change is <tt>istreambuf_iterator</tt> which returns
<tt>charT</tt> from <tt>operator*</tt> but has a reference type of
<tt>charT&amp;</tt>. We propose changing the reference type of
<tt>istreambuf_iterator</tt> to <tt>charT</tt>.
</p>
<p>The other option for resolving the issue with <tt>pointer</tt>,
mentioned in the note below, is to remove <tt>pointer</tt>
altogether. I prefer placing requirements on <tt>pointer</tt> to
removing it for two reasons. First, <tt>pointer</tt> will become
useful for implementing iterator adaptors and in particular,
<tt>reverse_iterator</tt> will become more well defined. Second,
removing <tt>pointer</tt> is a rather drastic and publicly-visible
action to take.</p>
<p>The proposed resolution technically enlarges the requirements for
iterators, which means there are existing iterators (such as
<tt>istreambuf_iterator</tt>, and potentially some programmer-defined
iterators) that will no longer meet the requirements. Will this break
existing code? The scenario in which it would is if an algorithm
implementation (say in the Standard Library) is changed to rely on
<tt>iterator_traits::reference</tt>, and then is used with one of the
iterators that do not have an appropriately defined
<tt>iterator_traits::reference</tt>.
</p>
<p>The proposed resolution makes one other subtle change. Previously,
it was required that output iterators have a <tt>difference_type</tt>
and <tt>value_type</tt> of <tt>void</tt>, which means that a forward
iterator could not be an output iterator. This is clearly a mistake,
so I've changed the wording to say that those types may be
<tt>void</tt>.
</p>
<p><b>Proposed resolution:</b></p>
<p>In 24.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.iterator.traits"> [lib.iterator.traits]</a>, after:</p>
<blockquote>
be defined as the iterator's difference type, value type and iterator
category, respectively.
</blockquote>
<p>add</p>
<blockquote>
In addition, the types
<pre>iterator_traits&lt;Iterator&gt;::reference
iterator_traits&lt;Iterator&gt;::pointer
</pre>
must be defined as the iterator's reference and pointer types, that
is, the same type as the type of <tt>*a</tt> and <tt>a-&gt;</tt>,
respectively.
</blockquote>
<p>In 24.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.iterator.traits"> [lib.iterator.traits]</a>, change:</p>
<blockquote>
In the case of an output iterator, the types
<pre>iterator_traits&lt;Iterator&gt;::difference_type
iterator_traits&lt;Iterator&gt;::value_type
</pre>
are both defined as <tt>void</tt>.
</blockquote>
<p>to:</p>
<blockquote>
In the case of an output iterator, the types
<pre>iterator_traits&lt;Iterator&gt;::difference_type
iterator_traits&lt;Iterator&gt;::value_type
iterator_traits&lt;Iterator&gt;::reference
iterator_traits&lt;Iterator&gt;::pointer
</pre>
may be defined as <tt>void</tt>.
</blockquote>
<p>In 24.5.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.istreambuf.iterator"> [lib.istreambuf.iterator]</a>, change:</p>
<blockquote>
<pre>typename traits::off_type, charT*, charT&amp;&gt;
</pre>
</blockquote>
<p>to:</p>
<blockquote>
<pre>typename traits::off_type, charT*, charT&gt;
</pre>
</blockquote>
<p><i>[
Redmond: there was concern in Sydney that this might not be the only place
where things were underspecified and needed to be changed. Jeremy
reviewed iterators in the standard and confirmed that nothing else
needed to be changed.
]</i></p>
<hr>
<a name="446"></a><h3><a name="446">446.&nbsp;Iterator equality between different containers</a></h3><p><b>Section:</b>&nbsp;24.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a>, 23.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Andy Koenig&nbsp; <b>Date:</b>&nbsp;16 Dec 2003</p>
<p>
What requirements does the standard place on equality comparisons between
iterators that refer to elements of different containers. For example, if
v1 and v2 are empty vectors, is v1.end() == v2.end() allowed to yield true?
Is it allowed to throw an exception?
</p>
<p>
The standard appears to be silent on both questions.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Sydney: The intention is that comparing two iterators from
different containers is undefined, but it's not clear if we say that,
or even whether it's something we should be saying in clause 23 or in
clause 24. Intuitively we might want to say that equality is defined
only if one iterator is reachable from another, but figuring out how
to say it in any sensible way is a bit tricky: reachability is defined
in terms of equality, so we can't also define equality in terms of
reachability.
]</i></p>
<hr>
<a name="453"><h3>453.&nbsp;basic_stringbuf::seekoff need not always fail for an empty stream</h3></a><p><b>Section:</b>&nbsp;27.7.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.stringbuf.virtuals"> [lib.stringbuf.virtuals]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Bill Plauger&nbsp; <b>Date:</b>&nbsp;30 Jan 2004</p>
<pre> pos_type basic_stringbuf::seekoff(off_type, ios_base::seekdir,
ios_base::openmode);
</pre>
<p>
is obliged to fail if nothing has been inserted into the stream. This
is unnecessary and undesirable. It should be permissible to seek to
an effective offset of zero.</p>
<p><i>[
Sydney: Agreed that this is an annoying problem: seeking to zero should be
legal. Bill will provide wording.
]</i></p>
<p><b>Proposed resolution:</b></p>
<p>Change the sentence from:</p>
<blockquote>
For a sequence to be positioned, if its next pointer (either
gptr() or pptr()) is a null pointer, the positioning operation
fails.
</blockquote>
<p>to:</p>
<blockquote>
For a sequence to be positioned, if its next pointer (either
gptr() or pptr()) is a null pointer and the new offset newoff
is nonzero, the positioning operation fails.
</blockquote>
<hr>
<a name="454"><h3>454.&nbsp;basic_filebuf::open should accept wchar_t names</h3></a><p><b>Section:</b>&nbsp;27.8.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.filebuf.members"> [lib.filebuf.members]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Bill Plauger&nbsp; <b>Date:</b>&nbsp;30 Jan 2004</p>
<pre> basic_filebuf *basic_filebuf::open(const char *, ios_base::open_mode);
</pre>
<p>should be supplemented with the overload:</p>
<pre> basic_filebuf *basic_filebuf::open(const wchar_t *, ios_base::open_mode);
</pre>
<p>
Depending on the operating system, one of these forms is fundamental and
the other requires an implementation-defined mapping to determine the
actual filename.
</p>
<p><i>[Sydney: Yes, we want to allow wchar_t filenames. Bill will
provide wording.]</i></p>
<p><b>Proposed resolution:</b></p>
<p>Change from:</p>
<blockquote>
<pre>basic_filebuf&lt;charT,traits&gt;* open(
const char* s,
ios_base::openmode mode );
</pre>
<p>
Effects: If is_open() != false, returns a null pointer.
Otherwise, initializes the filebuf as required. It then
opens a file, if possible, whose name is the NTBS s ("as if"
by calling std::fopen(s,modstr)).</p>
</blockquote>
<p>to:</p>
<blockquote>
<pre>basic_filebuf&lt;charT,traits&gt;* open(
const char* s,
ios_base::openmode mode );
basic_filebuf&lt;charT,traits&gt;* open(
const wchar_t* ws,
ios_base::openmode mode );
</pre>
<p>
Effects: If is_open() != false, returns a null pointer.
Otherwise, initializes the filebuf as required. It then
opens a file, if possible, whose name is the NTBS s ("as if"
by calling std::fopen(s,modstr)).
For the second signature, the NTBS s is determined from the
WCBS ws in an implementation-defined manner.
</p>
<p>
(NOTE: For a system that "naturally" represents a filename
as a WCBS, the NTBS s in the first signature may instead
be mapped to a WCBS; if so, it follows the same mapping
rules as the first argument to open.)
</p>
</blockquote>
<p><b>Rationale:</b></p>
<p>
Slightly controversial, but by a 7-1 straw poll the LWG agreed to move
this to Ready. The controversy was because the mapping between wide
names and files in a filesystem is implementation defined. The
counterargument, which most but not all LWG members accepted, is that
the mapping between narrow files names and files is also
implemenation defined.</p>
<hr>
<a name="455"><h3>455.&nbsp;cerr::tie() and wcerr::tie() are overspecified</h3></a><p><b>Section:</b>&nbsp;27.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.iostream.objects"> [lib.iostream.objects]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Bill Plauger&nbsp; <b>Date:</b>&nbsp;30 Jan 2004</p>
<p>
Both cerr::tie() and wcerr::tie() are obliged to be null at program
startup. This is overspecification and overkill. It is both traditional
and useful to tie cerr to cout, to ensure that standard output is drained
whenever an error message is written. This behavior should at least be
permitted if not required. Same for wcerr::tie().
</p>
<p><b>Proposed resolution:</b></p>
<p>Add to the description of cerr:</p>
<blockquote>
After the object cerr is initialized, cerr.tie() returns &amp;cout.
Its state is otherwise the same as required for basic_ios&lt;char&gt;::init
(lib.basic.ios.cons).
</blockquote>
<p>Add to the description of wcerr:</p>
<blockquote>
After the object wcerr is initialized, wcerr.tie() returns &amp;wcout.
Its state is otherwise the same as required for basic_ios&lt;wchar_t&gt;::init
(lib.basic.ios.cons).
</blockquote>
<p><i>[Sydney: straw poll (3-1): we should <i>require</i>, not just
permit, cout and cerr to be tied on startup. Pre-Redmond: Bill will
provide wording.]</i></p>
<hr>
<a name="456"><h3>456.&nbsp;Traditional C header files are overspecified</h3></a><p><b>Section:</b>&nbsp;17.4.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.headers"> [lib.headers]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Bill Plauger&nbsp; <b>Date:</b>&nbsp;30 Jan 2004</p>
<p>The C++ Standard effectively requires that the traditional C headers
(of the form &lt;xxx.h&gt;) be defined in terms of the newer C++
headers (of the form &lt;cxxx&gt;). Clauses 17.4.1.2/4 and D.5 combine
to require that:</p>
<ul>
<li>Including the header &lt;cxxx&gt; declares a C name in namespace std.</li>
<li> Including the header &lt;xxx.h&gt; declares a C name in namespace std
(effectively by including &lt;cxxx&gt;), then imports it into the global
namespace with an individual using declaration.</li>
</ul>
<p>
The rules were left in this form despited repeated and heated objections
from several compiler vendors. The C headers are often beyond the direct
control of C++ implementors. In some organizations, it's all they can do
to get a few #ifdef __cplusplus tests added. Third-party library vendors
can perhaps wrap the C headers. But neither of these approaches supports
the drastic restructuring required by the C++ Standard. As a result, it is
still widespread practice to ignore this conformance requirement, nearly
seven years after the committee last debated this topic. Instead, what is
often implemented is:
</p>
<ul>
<li> Including the header &lt;xxx.h&gt; declares a C name in the
global namespace.</li>
<li> Including the header &lt;cxxx&gt; declares a C name in the
global namespace (effectively by including &lt;xxx.h&gt;), then
imports it into namespace std with an individual using declaration.</li>
</ul>
<p>
The practical benefit for implementors with the second approach is that
they can use existing C library headers, as they are pretty much obliged
to do. The practical cost for programmers facing a mix of implementations
is that they have to assume weaker rules:</p>
<ul>
<li> If you want to assuredly declare a C name in the global
namespace, include &lt;xxx.h&gt;. You may or may not also get the
declaration in namespace std.</li>
<li> If you want to assuredly declare a C name in namespace std,
include &lt;cxxx.h&gt;. You may or may not also get the declaration in
the global namespace.</li>
</ul>
<p>
There also exists the <i>possibility</i> of subtle differences due to
Koenig lookup, but there are so few non-builtin types defined in the C
headers that I've yet to see an example of any real problems in this
area.
</p>
<p>
It is worth observing that the rate at which programmers fall afoul of
these differences has remained small, at least as measured by newsgroup
postings and our own bug reports. (By an overwhelming margin, the
commonest problem is still that programmers include &lt;string&gt; and can't
understand why the typename string isn't defined -- this a decade after
the committee invented namespace std, nominally for the benefit of all
programmers.)
</p>
<p>
We should accept the fact that we made a serious mistake and rectify it,
however belatedly, by explicitly allowing either of the two schemes for
declaring C names in headers.
</p>
<p><i>[Sydney: This issue has been debated many times, and will
certainly have to be discussed in full committee before any action
can be taken. However, the preliminary sentiment of the LWG was in
favor of the change. (6 yes, 0 no, 2 abstain) Robert Klarer
suggests that we might also want to undeprecate the
C-style <tt>.h</tt> headers.]</i></p>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="457"><h3>457.&nbsp;bitset constructor: incorrect number of initialized bits</h3></a><p><b>Section:</b>&nbsp;23.3.5.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.bitset.cons"> [lib.bitset.cons]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Dag Henriksson&nbsp; <b>Date:</b>&nbsp;30 Jan 2004</p>
<p>
The constructor from unsigned long says it initializes "the first M
bit positions to the corresponding bit values in val. M is the smaller
of N and the value CHAR_BIT * sizeof(unsigned long)."
</p>
<p>
Object-representation vs. value-representation strikes again. CHAR_BIT *
sizeof (unsigned long) does not give us the number of bits an unsigned long
uses to hold the value. Thus, the first M bit position above is not
guaranteed to have any corresponding bit values in val.
</p>
<p><b>Proposed resolution:</b></p>
<p>In 23.3.5.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.bitset.cons"> [lib.bitset.cons]</a> paragraph 2, change "M is the smaller of
N and the value CHAR_BIT * sizeof (unsigned long). (249)" to
"<tt>M</tt> is the smaller of <tt>N</tt> and the number of bits in
the value representation (section 3.9 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/basic.html#basic.types"> [basic.types]</a>) of <tt>unsigned
long</tt>."
</p>
<hr>
<a name="458"><h3>458.&nbsp;24.1.5 contains unintented limitation for operator-</h3></a><p><b>Section:</b>&nbsp;24.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.random.access.iterators"> [lib.random.access.iterators]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Daniel Frey&nbsp; <b>Date:</b>&nbsp;27 Feb 2004</p>
<p>
In 24.1.5 [lib.random.access.iterators], table 76 the operational
semantics for the expression "r -= n" are defined as "return r += -n".
This means, that the expression -n must be valid, which is not the case
for unsigned types.
</p>
<p><i>[
Sydney: Possibly not a real problem, since difference type is required
to be a signed integer type. However, the wording in the standard may
be less clear than we would like.
]</i></p>
<p><b>Proposed resolution:</b></p>
<p>
To remove this limitation, I suggest to change the
operational semantics for this column to:
</p>
<code>
{ Distance m = n;
if (m &gt;= 0)
while (m--) --r;
else
while (m++) ++r;
return r; }
</code>
<hr>
<a name="459"><h3>459.&nbsp;Requirement for widening in stage 2 is overspecification</h3></a><p><b>Section:</b>&nbsp;22.2.2.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.facet.num.get.virtuals"> [lib.facet.num.get.virtuals]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;16 Mar 2004</p>
<p>When parsing strings of wide-character digits, the standard
requires the library to widen narrow-character "atoms" and compare
the widened atoms against the characters that are being parsed.
Simply narrowing the wide characters would be far simpler, and
probably more efficient. The two choices are equivalent except in
convoluted test cases, and many implementations already ignore the
standard and use narrow instead of widen.</p>
<p>
First, I disagree that using narrow() instead of widen() would
necessarily have unfortunate performance implications. A possible
implementation of narrow() that allows num_get to be implemented
in a much simpler and arguably comparably efficient way as calling
widen() allows, i.e. without making a virtual call to do_narrow every
time, is as follows:
</p>
<pre> inline char ctype&lt;wchar_t&gt;::narrow (wchar_t wc, char dflt) const
{
const unsigned wi = unsigned (wc);
if (wi &gt; UCHAR_MAX)
return typeid (*this) == typeid (ctype&lt;wchar_t&gt;) ?
dflt : do_narrow (wc, dflt);
if (narrow_ [wi] &lt; 0) {
const char nc = do_narrow (wc, dflt);
if (nc == dflt)
return dflt;
narrow_ [wi] = nc;
}
return char (narrow_ [wi]);
}
</pre>
<p>
Second, I don't think the change proposed in the issue (i.e., to use
narrow() instead of widen() during Stage 2) would be at all
drastic. Existing implementations with the exception of libstdc++
currently already use narrow() so the impact of the change on programs
would presumably be isolated to just a single implementation. Further,
since narrow() is not required to translate alternate wide digit
representations such as those mentioned in issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#303">303</a> to
their narrow equivalents (i.e., the portable source characters '0'
through '9'), the change does not necessarily imply that these
alternate digits would be treated as ordinary digits and accepted as
part of numbers during parsing. In fact, the requirement in 22.2.1.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.locale.ctype.virtuals"> [lib.locale.ctype.virtuals]</a>, p13 forbids narrow() to translate an alternate
digit character, wc, to an ordinary digit in the basic source
character set unless the expression
(ctype&lt;charT&gt;::is(ctype_base::digit, wc) == true) holds. This in
turn is prohibited by the C standard (7.25.2.1.5, 7.25.2.1.5, and
5.2.1, respectively) for charT of either char or wchar_t.
</p>
<p><i>[Sydney: To a large extent this is a nonproblem. As long as
you're only trafficking in char and wchar_t we're only dealing with a
stable character set, so you don't really need either 'widen' or
'narrow': can just use literals. Finally, it's not even clear whether
widen-vs-narrow is the right question; arguably we should be using
codecvt instead.]</i></p>
<p><b>Proposed resolution:</b></p>
<p>Change stage 2 so that implementations are permitted to use either
technique to perform the comparison:</p>
<ol>
<li> call widen on the atoms and compare (either by using
operator== or char_traits&lt;charT&gt;::eq) the input with
the widened atoms, or</li>
<li> call narrow on the input and compare the narrow input
with the atoms</li>
<li> do (1) or (2) only if charT is not char or wchar_t,
respectively; i.e., avoid calling widen or narrow
if it the source and destination types are the same</li>
</ol>
<hr>
<a name="460"><h3>460.&nbsp;Default modes missing from basic_fstream member specifications</h3></a><p><b>Section:</b>&nbsp;27.8.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.fstreams"> [lib.fstreams]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Ben Hutchings&nbsp; <b>Date:</b>&nbsp;1 Apr 2004</p>
<p>
The second parameters of the non-default constructor and of the open
member function for basic_fstream, named "mode", are optional
according to the class declaration in 27.8.1.11 [lib.fstream]. The
specifications of these members in 27.8.1.12 [lib.fstream.cons] and
27.8.1.13 lib.fstream.members] disagree with this, though the
constructor declaration has the "explicit" function-specifier implying
that it is intended to be callable with one argument.
</p>
<p><b>Proposed resolution:</b></p>
<p>In 27.8.1.12 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.fstream.cons"> [lib.fstream.cons]</a>, change</p>
<pre> explicit basic_fstream(const char* s, ios_base::openmode mode);
</pre>
<p>to</p>
<pre> explicit basic_fstream(const char* s,
ios_base::openmode mode = ios_base::in|ios_base::out);
</pre>
<p>In 27.8.1.13 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.fstream.members"> [lib.fstream.members]</a>, change</p>
<pre> void open(const char*s, ios_base::openmode mode);
</pre>
<p>to</p>
void open(const char*s,
ios_base::openmode mode = ios_base::in|ios_base::out);
<hr>
<a name="461"><h3>461.&nbsp;time_get hard or impossible to implement</h3></a><p><b>Section:</b>&nbsp;22.2.5.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.locale.time.get.virtuals"> [lib.locale.time.get.virtuals]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a>&nbsp; <b>Submitter:</b>&nbsp;Bill Plauger&nbsp; <b>Date:</b>&nbsp;23 Mar 2004</p>
<p>
Template time_get currently contains difficult, if not impossible,
requirements for do_date_order, do_get_time, and do_get_date. All require
the implementation to scan a field generated by the %x or %X conversion
specifier in strftime. Yes, do_date_order can always return no_order, but
that doesn't help the other functions. The problem is that %x can be
nearly anything, and it can vary widely with locales. It's horribly
onerous to have to parse "third sunday after Michaelmas in the year of
our Lord two thousand and three," but that's what we currently ask of
do_get_date. More practically, it leads some people to think that if
%x produces 10.2.04, we should know to look for dots as separators. Still
not easy.
</p>
<p>
Note that this is the <i>opposite</i> effect from the intent stated in the
footnote earlier in this subclause:
</p>
<blockquote>
"In other words, user confirmation is required for reliable parsing of
user-entered dates and times, but machine-generated formats can be
parsed reliably. This allows parsers to be aggressive about interpreting
user variations on standard formats."
</blockquote>
<p>
We should give both implementers and users an easier and more reliable
alternative: provide a (short) list of alternative delimiters and say
what the default date order is for no_order. For backward compatibility,
and maximum latitude, we can permit an implementation to parse whatever
%x or %X generates, but we shouldn't require it.
</p>
<p><b>Proposed resolution:</b></p>
<p><b>In the description:</b></p>
<pre>iter_type do_get_time(iter_type s, iter_type end, ios_base&amp; str,
ios_base::iostate&amp; err, tm* t) const;
</pre>
<p>
2 Effects: Reads characters starting at suntil it has extracted those
struct tm members, and remaining format characters, used by
time_put&lt;&gt;::put to produce the format specified by 'X', or until it
encounters an error or end of sequence.
</p>
<p><b>change:</b> 'X'</p>
<p><b>to:</b> "%H:%M:%S"</p>
<p><b>In the description:</b></p>
<pre>iter_type do_get_date(iter_type s, iter_type end, ios_base&amp; str,
ios_base::iostate&amp; err, tm* t) const;
</pre>
<p>
4 Effects: Reads characters starting at suntil it has extracted those
struct tm members, and remaining format characters, used by
time_put&lt;&gt;::put to produce the format specified by 'x', or until it
encounters an error.
</p>
<p>
<b>change:</b> used by time_put&lt;&gt;::put to produce the format
specified by 'x', or until it encounters an error.
</p>
<p><b>to:</b> used by time_put&lt;&gt;:: put to produce one of the
following formats, or until it encounters an error. The format depends
on the value returned by date_order() as follows:
</p>
<pre> date_order() format
no_order "%m/%d/%y"
dmy "%d/%m/%y"
mdy "%m/%d/%y"
ymd "%y/%m/%d"
ydm "%y/%d/%m"
</pre>
<p><i>[Redmond: agreed that this is a real problem. The solution is
probably to match C99's parsing rules. Bill provided wording.
]</i></p>
<hr>
<a name="462"><h3>462.&nbsp;Destroying objects with static storage duration</h3></a><p><b>Section:</b>&nbsp;3.6.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/basic.html#basic.start.term"> [basic.start.term]</a>, 18.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-support.html#lib.support.start.term"> [lib.support.start.term]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Bill Plauger&nbsp; <b>Date:</b>&nbsp;23 Mar 2004</p>
<p>
3.6.3 Termination spells out in detail the interleaving of static
destructor calls and calls to functions registered with atexit. To
match this behavior requires intimate cooperation between the code
that calls destructors and the exit/atexit machinery. The former
is tied tightly to the compiler; the latter is a primitive mechanism
inherited from C that traditionally has nothing to do with static
construction and destruction. The benefits of intermixing destructor
calls with atexit handler calls is questionable at best, and <i>very</i>
difficult to get right, particularly when mixing third-party C++
libraries with different third-party C++ compilers and C libraries
supplied by still other parties.
</p>
<p>
I believe the right thing to do is defer all static destruction
until after all atexit handlers are called. This is a change in
behavior, but one that is likely visible only to perverse test
suites. At the very least, we should <i>permit</i> deferred destruction
even if we don't require it.
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[If this is to be changed, it should probably be changed by CWG.
At this point, however, the LWG is leaning toward NAD. Implementing
what the standard says is hard work, but it's not impossible and
most vendors went through that pain years ago. Changing this
behavior would be a user-visible change, and would break at least
one real application.]</i></p>
<p>
</p>
<hr>
<a name="463"><h3>463.&nbsp;auto_ptr usability issues</h3></a><p><b>Section:</b>&nbsp;20.4.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.auto.ptr"> [lib.auto.ptr]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Rani Sharoni&nbsp; <b>Date:</b>&nbsp;7 Dec 2003</p>
<p>
TC1 CWG DR #84 effectively made the template&lt;class Y&gt; operator auto_ptr&lt;Y&gt;()
member of auto_ptr (20.4.5.3/4) obsolete.
</p>
<p>
The sole purpose of this obsolete conversion member is to enable copy
initialization base from r-value derived (or any convertible types like
cv-types) case:
</p>
<pre>#include &lt;memory&gt;
using std::auto_ptr;
struct B {};
struct D : B {};
auto_ptr&lt;D&gt; source();
int sink(auto_ptr&lt;B&gt;);
int x1 = sink( source() ); // #1 EDG - no suitable copy constructor
</pre>
<p>
The excellent analysis of conversion operations that was given in the final
auto_ptr proposal
(http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/1997/N1128.pdf)
explicitly specifies this case analysis (case 4). DR #84 makes the analysis
wrong and actually comes to forbid the loophole that was exploited by the
auto_ptr designers.
</p>
<p>
I didn't encounter any compliant compiler (e.g. EDG, GCC, BCC and VC) that
ever allowed this case. This is probably because it requires 3 user defined
conversions and in fact current compilers conform to DR #84.
</p>
<p>
I was surprised to discover that the obsolete conversion member actually has
negative impact of the copy initialization base from l-value derived
case:</p>
<pre>auto_ptr&lt;D&gt; dp;
int x2 = sink(dp); // #2 EDG - more than one user-defined conversion applies
</pre>
<p>
I'm sure that the original intention was allowing this initialization using
the template&lt;class Y&gt; auto_ptr(auto_ptr&lt;Y&gt;&amp; a) constructor (20.4.5.1/4) but
since in this copy initialization it's merely user defined conversion (UDC)
and the obsolete conversion member is UDC with the same rank (for the early
overloading stage) there is an ambiguity between them.
</p>
<p>
Removing the obsolete member will have impact on code that explicitly
invokes it:
</p>
<pre>int y = sink(source().operator auto_ptr&lt;B&gt;());
</pre>
<p>
IMHO no one ever wrote such awkward code and the reasonable workaround for
#1 is:
</p>
<pre>int y = sink( auto_ptr&lt;B&gt;(source()) );
</pre>
<p>
I was even more surprised to find out that after removing the obsolete
conversion member the initialization was still ill-formed:
int x3 = sink(dp); // #3 EDG - no suitable copy constructor
</p>
<p>
This copy initialization semantically requires copy constructor which means
that both template conversion constructor and the auto_ptr_ref conversion
member (20.4.5.3/3) are required which is what was explicitly forbidden in
DR #84. This is a bit amusing case in which removing ambiguity results with
no candidates.
</p>
<p>
I also found exception safety issue with auto_ptr related to auto_ptr_ref:
</p>
<pre>int f(auto_ptr&lt;B&gt;, std::string);
auto_ptr&lt;B&gt; source2();
// string constructor throws while auto_ptr_ref
// "holds" the pointer
int x4 = f(source2(), "xyz"); // #4
</pre>
<p>
The theoretic execution sequence that will cause a leak:
</p>
<ol>
<li>call auto_ptr&lt;B&gt;::operator auto_ptr_ref&lt;B&gt;()</li>
<li>call string::string(char const*) and throw</li>
</ol>
<p>
According to 20.4.5.3/3 and 20.4.5/2 the auto_ptr_ref conversion member
returns auto_ptr_ref&lt;Y&gt; that holds *this and this is another defect since
the type of *this is auto_ptr&lt;X&gt; where X might be different from Y. Several
library vendors (e.g. SGI) implement auto_ptr_ref&lt;Y&gt; with Y* as member which
is much more reasonable. Other vendor implemented auto_ptr_ref as
defectively required and it results with awkward and catastrophic code:
int oops = sink(auto_ptr&lt;B&gt;(source())); // warning recursive on all control
paths
</p>
<p>
Dave Abrahams noticed that there is no specification saying that
auto_ptr_ref copy constructor can't throw.
</p>
<p>
My proposal comes to solve all the above issues and significantly simplify
auto_ptr implementation. One of the fundamental requirements from auto_ptr
is that it can be constructed in an intuitive manner (i.e. like ordinary
pointers) but with strict ownership semantics which yield that source
auto_ptr in initialization must be non-const. My idea is to add additional
constructor template with sole propose to generate ill-formed, diagnostic
required, instance for const auto_ptr arguments during instantiation of
declaration. This special constructor will not be instantiated for other
types which is achievable using 14.8.2/2 (SFINAE). Having this constructor
in hand makes the constructor template&lt;class Y&gt; auto_ptr(auto_ptr&lt;Y&gt; const&amp;)
legitimate since the actual argument can't be const yet non const r-value
are acceptable.
</p>
<p>
This implementation technique makes the "private auxiliary class"
auto_ptr_ref obsolete and I found out that modern C++ compilers (e.g. EDG,
GCC and VC) consume the new implementation as expected and allow all
intuitive initialization and assignment cases while rejecting illegal cases
that involve const auto_ptr arguments.
</p>
<p>The proposed auto_ptr interface:</p>
<pre>namespace std {
template&lt;class X&gt; class auto_ptr {
public:
typedef X element_type;
// 20.4.5.1 construct/copy/destroy:
explicit auto_ptr(X* p=0) throw();
auto_ptr(auto_ptr&amp;) throw();
template&lt;class Y&gt; auto_ptr(auto_ptr&lt;Y&gt; const&amp;) throw();
auto_ptr&amp; operator=(auto_ptr&amp;) throw();
template&lt;class Y&gt; auto_ptr&amp; operator=(auto_ptr&lt;Y&gt;) throw();
~auto_ptr() throw();
// 20.4.5.2 members:
X&amp; operator*() const throw();
X* operator-&gt;() const throw();
X* get() const throw();
X* release() throw();
void reset(X* p=0) throw();
private:
template&lt;class U&gt;
auto_ptr(U&amp; rhs, typename
unspecified_error_on_const_auto_ptr&lt;U&gt;::type = 0);
};
}
</pre>
<p>
One compliant technique to implement the unspecified_error_on_const_auto_ptr
helper class is using additional private auto_ptr member class template like
the following:
</p>
<pre>template&lt;typename T&gt; struct unspecified_error_on_const_auto_ptr;
template&lt;typename T&gt;
struct unspecified_error_on_const_auto_ptr&lt;auto_ptr&lt;T&gt; const&gt;
{ typedef typename auto_ptr&lt;T&gt;::const_auto_ptr_is_not_allowed type; };
</pre>
<p>
There are other techniques to implement this helper class that might work
better for different compliers (i.e. better diagnostics) and therefore I
suggest defining its semantic behavior without mandating any specific
implementation. IMO, and I didn't found any compiler that thinks otherwise,
14.7.1/5 doesn't theoretically defeat the suggested technique but I suggest
verifying this with core language experts.
</p>
<p><b>Further changes in standard text:</b></p>
<p>Remove section 20.4.5.3</p>
<p>Change 20.4.5/2 to read something like:
Initializing auto_ptr&lt;X&gt; from const auto_ptr&lt;Y&gt; will result with unspecified
ill-formed declaration that will require unspecified diagnostic.</p>
<p>Change 20.4.5.1/4,5,6 to read:</p>
<pre>template&lt;class Y&gt; auto_ptr(auto_ptr&lt;Y&gt; const&amp; a) throw();</pre>
<p> 4 Requires: Y* can be implicitly converted to X*.</p>
<p> 5 Effects: Calls const_cast&lt;auto_ptr&lt;Y&gt;&amp;&gt;(a).release().</p>
<p> 6 Postconditions: *this holds the pointer returned from a.release().</p>
<p>Change 20.4.5.1/10</p>
<pre>template&lt;class Y&gt; auto_ptr&amp; operator=(auto_ptr&lt;Y&gt; a) throw();
</pre>
<p>
10 Requires: Y* can be implicitly converted to X*. The expression delete
get() is well formed.
</p>
<p>LWG TC DR #127 is obsolete.</p>
<p>
Notice that the copy constructor and copy assignment operator should remain
as before and accept non-const auto_ptr&amp; since they have effect on the form
of the implicitly declared copy constructor and copy assignment operator of
class that contains auto_ptr as member per 12.8/5,10:
</p>
<pre>struct X {
// implicit X(X&amp;)
// implicit X&amp; operator=(X&amp;)
auto_ptr&lt;D&gt; aptr_;
};
</pre>
<p>
In most cases this indicates about sloppy programming but preserves the
current auto_ptr behavior.
</p>
<p>
Dave Abrahams encouraged me to suggest fallback implementation in case that
my suggestion that involves removing of auto_ptr_ref will not be accepted.
In this case removing the obsolete conversion member to auto_ptr&lt;Y&gt; and
20.4.5.3/4,5 is still required in order to eliminate ambiguity in legal
cases. The two constructors that I suggested will co exist with the current
members but will make auto_ptr_ref obsolete in initialization contexts.
auto_ptr_ref will be effective in assignment contexts as suggested in DR
#127 and I can't see any serious exception safety issues in those cases
(although it's possible to synthesize such). auto_ptr_ref&lt;X&gt; semantics will
have to be revised to say that it strictly holds pointer of type X and not
reference to an auto_ptr for the favor of cases in which auto_ptr_ref&lt;Y&gt; is
constructed from auto_ptr&lt;X&gt; in which X is different from Y (i.e. assignment
from r-value derived to base).
</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Redmond: punt for the moment. We haven't decided yet whether we
want to fix auto_ptr for C++-0x, or remove it and replace it with
move_ptr and unique_ptr.]</i></p>
<hr>
<a name="464"><h3>464.&nbsp;Suggestion for new member functions in standard containers</h3></a><p><b>Section:</b>&nbsp;23.2.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector"> [lib.vector]</a>, 23.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.map"> [lib.map]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a>&nbsp; <b>Submitter:</b>&nbsp;Thorsten Ottosen&nbsp; <b>Date:</b>&nbsp;12 May 2004</p>
<p>To add slightly more convenience to vector&lt;T&gt; and map&lt;Key,T&gt; we should consider to add</p>
<ol>
<li> add vector&lt;T&gt;::data() member (const and non-const version)
semantics: if( empty() ) return 0; else return buffer_;</li>
<li> add map&lt;Key,T&gt;::at( const Key&amp; k ) member (const and non-const version)
<i>semantics</i>: iterator i = find( k ); if( i != end() ) return *i; else throw range_error();</li>
</ol>
<p>Rationale:</p>
<ul>
<li>To obtain a pointer to the vector's buffer, one must use either
operator[]() (which can give undefined behavior for empty vectors) or
at() (which will then throw if the vector is empty). </li>
<li>tr1::array&lt;T,sz&gt; already has a data() member</li>
<li>e cannot use operator[]() when T is not DefaultDonstructible</li>
<li>Neither when the map is const.</li>
<li>when we want to make sure we don't add an element accidently</li>
<li>when it should be considered an error if a key is not in the map</li>
</ul>
<p><b>Proposed resolution:</b></p>
<p>In 23.2.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector"> [lib.vector]</a>, add the following to the <tt>vector</tt>
synopsis after "element access" and before "modifiers":</p>
<pre> // <i>[lib.vector.data] data access</i>
pointer data();
const_pointer data() const;
</pre>
<p>Add a new subsection of 23.2.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector"> [lib.vector]</a>:</p>
<blockquote>
<p>23.2.4.x <tt>vector</tt> data access</p>
<pre> pointer data();
const_pointer data() const;
</pre>
<p><b>Returns:</b> A pointer such that [data(), data() + size()) is a valid
range that contains the same elements as [begin(), end()).</p>
<p><b>Complexity:</b> Constant time.</p>
<p><b>Throws:</b> Nothing.</p>
</blockquote>
<p>In 23.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.map"> [lib.map]</a>, add the following to the <tt>map</tt>
synopsis immediately after the line for operator[]:</p>
<pre> T&amp; at(const key_type&amp; x);
const T&amp; at(const key_type&amp; x) const;
</pre>
<p>Add the following to 23.3.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.map.access"> [lib.map.access]</a>:</p>
<blockquote>
<pre> T&amp; at(const key_type&amp; x);
const T&amp; at(const key_type&amp; x) const;
</pre>
<p><b>Returns:</b> A reference to the element whose key is equivalent
to x, if such an element is present in the map.</p>
<p><b>Throws:</b> <tt>out_of_range</tt> if no such element is present.</p>
</blockquote>
<p><b>Rationale:</b></p>
<p>Neither of these additions provides any new functionality but the
LWG agreed that they are convenient, especially for novices. The
exception type chosen for <tt>at</tt>, <tt>std::out_of_range</tt>,
was chosen to match <tt>vector::at</tt>.</p>
<hr>
<a name="465"><h3>465.&nbsp;Contents of &lt;ciso646&gt;</h3></a><p><b>Section:</b>&nbsp;17.4.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.headers"> [lib.headers]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a>&nbsp; <b>Submitter:</b>&nbsp;Steve Clamage&nbsp; <b>Date:</b>&nbsp;3 Jun 2004</p>
<p>C header &lt;iso646.h&gt; defines macros for some operators, such as
not_eq for !=.</p>
<p>Section 17.4.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.headers"> [lib.headers]</a> "Headers" says that except as noted in
clauses 18 through 27, the &lt;cname&gt; C++ header contents are the same
as the C header &lt;name.h&gt;. In particular, table 12 lists
&lt;ciso646&gt; as a C++ header.</p>
<p>I don't find any other mention of &lt;ciso646&gt;, or any mention of
&lt;iso646.h&gt;, in clauses 17 thorough 27. That implies that the
contents of &lt;ciso646&gt; are the same as C header &lt;iso646.h&gt;.</p>
<p>Annex C (informative, not normative) in [diff.header.iso646.h] C.2.2.2
"Header &lt;iso646.h&gt;" says that the alternative tokens are not
defined as macros in &lt;ciso646&gt;, but does not mention the contents
of &lt;iso646.h&gt;.</p>
<p>I don't find any normative text to support C.2.2.2.</p>
<p><b>Proposed resolution:</b></p>
<p>Add to section 17.4.1.2 Headers [lib.headers] a new paragraph after
paragraph 6 (the one about functions must be functions):</p>
<blockquote>
<p>Identifiers that are keywords or operators in C++ shall not be defined
as macros in C++ standard library headers.
[Footnote:In particular, including the standard header &lt;iso646.h&gt;
or &lt;ciso646&gt; has no effect. </p>
</blockquote>
<p><i>[post-Redmond: Steve provided wording.]</i></p>
<hr>
<a name="466"><h3>466.&nbsp;basic_string ctor should prevent null pointer error</h3></a><p><b>Section:</b>&nbsp;21.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-strings.html#lib.string.cons"> [lib.string.cons]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Daniel Frey&nbsp; <b>Date:</b>&nbsp;10 Jun 2004</p>
<p>
Today, my colleagues and me wasted a lot of time. After some time, I
found the problem. It could be reduced to the following short example:
</p>
<pre> #include &lt;string&gt;
int main() { std::string( 0 ); }
</pre>
<p>The problem is that the tested compilers (GCC 2.95.2, GCC 3.3.1 and
Comeau online) compile the above without errors or warnings! The
programs (at least for the GCC) resulted in a SEGV.</p>
<p>I know that the standard explicitly states that the ctor of string
requires a char* which is not zero. STLs could easily detect the above
case with a private ctor for basic_string which takes a single 'int'
argument. This would catch the above code at compile time and would not
ambiguate any other legal ctors.</p>
<p><b>Proposed resolution:</b></p>
<p><i>[Redmond: No great enthusiasm for doing this. If we do,
however, we want to do it for all places that take <tt>charT*</tt>
pointers, not just the single-argument constructor. The other
question is whether we want to catch this at compile time (in which
case we catch the error of a literal 0, but not an expression whose
value is a null pointer), at run time, or both.]</i></p>
<hr>
<a name="467"><h3>467.&nbsp;char_traits::lt(), compare(), and memcmp()</h3></a><p><b>Section:</b>&nbsp;21.1.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-strings.html#lib.char.traits.specializations.char"> [lib.char.traits.specializations.char]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;28 Jun 2004</p>
<p>
Table 37 describes the requirements on Traits::compare() in terms of
those on Traits::lt(). 21.1.3.1, p6 requires char_traits&lt;char&gt;::lt()
to yield the same result as operator&lt;(char, char).
</p>
<p>
Most, if not all, implementations of char_traits&lt;char&gt;::compare()
call memcmp() for efficiency. However, the C standard requires both
memcmp() and strcmp() to interpret characters under comparison as
unsigned, regardless of the signedness of char. As a result, all
these char_traits implementations fail to meet the requirement
imposed by Table 37 on compare() when char is signed.
</p>
<p>Read email thread starting with c++std-lib-13499 for more. </p>
<p><b>Proposed resolution:</b></p>
<p>Change 21.1.3.1, p6 from</p>
<blockquote>
The two-argument members assign, eq, and lt are defined identically
to the built-in operators =, ==, and &lt; respectively.
</blockquote>
<p>to</p>
<blockquote>
The two-argument member assign is defined identically to
the built-in operators = and == respectively. The two
argument members eq and lt are defined identically to
the built-in operators == and &lt; for type unsigned char.
</blockquote>
<p><i>[Redmond: The LWG agreed with this general direction, but we
also need to change <tt>eq</tt> to be consistent with this change.
Post-Redmond: Martin provided wording.]</i></p>
<hr>
<a name="468"><h3>468.&nbsp;unexpected consequences of ios_base::operator void*()</h3></a><p><b>Section:</b>&nbsp;27.4.4.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.iostate.flags"> [lib.iostate.flags]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;28 Jun 2004</p>
<p>The program below is required to compile but when run it typically
produces unexpected results due to the user-defined conversion from
std::cout or any object derived from basic_ios to void*.
</p>
<pre> #include &lt;cassert&gt;
#include &lt;iostream&gt;
int main ()
{
assert (std::cin.tie () == std::cout);
// calls std::cout.ios::operator void*()
}
</pre>
<p><b>Proposed resolution:</b></p>
<p>
Replace std::basic_ios&lt;charT, traits&gt;::operator void*() with another
conversion operator to some unspecified type that is guaranteed not
to be convertible to any other type except for bool (a pointer-to-member
might be one such suitable type). In addition, make it clear that the
pointer type need not be a pointer to a complete type and when non-null,
the value need not be valid.
</p>
<p>Specifically, change in [lib.ios] the signature of</p>
<pre> operator void*() const;
</pre>
<p>to</p>
<pre> operator unspecified_pointer_type () const;
</pre>
<p>and change [lib.iostate.flags], p1 from</p>
<pre> operator void*() const;
</pre>
<p>to</p>
<pre> operator unspecified_pointer_type() const;
-1- Returns: If fail() then a null pointer; otherwise some
non-null but not necessarily valid pointer to indicate
success.
-2- Note: The type named unspecified_pointer_type above is a pointer
to some unspecified, possibly incomplete type, that is guaranteed
not to be convertible to any other type except bool.(Footnote 1)
--
Footnote 1: A pointer-to-member might be one such suitable type.
</pre>
<p><i>[Redmond: 5-4 straw poll in favor of doing this.]</i></p>
<hr>
<a name="469"><h3>469.&nbsp;vector&lt;bool&gt; ill-formed relational operators</h3></a><p><b>Section:</b>&nbsp;23.2.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.bool"> [lib.vector.bool]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;28 Jun 2004</p>
<p>
The overloads of relational operators for vector&lt;bool&gt; specified
in [lib.vector.bool] are redundant (they are semantically identical
to those provided for the vector primary template) and may even be
diagnosed as ill-formed (refer to Daveed Vandevoorde's explanation
in c++std-lib-13647).
</p>
<p><b>Proposed resolution:</b></p>
<p>
Remove all overloads of overloads of relational operators for
vector&lt;bool&gt; from [lib.vector.bool].
</p>
<hr>
<a name="470"><h3>470.&nbsp;accessing containers from their elements' special functions</h3></a><p><b>Section:</b>&nbsp;23 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.containers"> [lib.containers]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;28 Jun 2004</p>
<p>
The standard doesn't prohibit the destructors (or any other special
functions) of containers' elements invoked from a member function
of the container from "recursively" calling the same (or any other)
member function on the same container object, potentially while the
container is in an intermediate state, or even changing the state
of the container object while it is being modified. This may result
in some surprising (i.e., undefined) behavior.
</p>
<p>Read email thread starting with c++std-lib-13637 for more.</p>
<p><b>Proposed resolution:</b></p>
<p>Add to Container Requirements the following new paragraph:</p>
<pre> Unless otherwise specified, the behavior of a program that
invokes a container member function f from a member function
g of the container's value_type on a container object c that
called g from its mutating member function h, is undefined.
I.e., if v is an element of c, directly or indirectly calling
c.h() from v.g() called from c.f(), is undefined.
</pre>
<p><i>[Redmond: This is a real issue, but it's probably a clause 17
issue, not clause 23. We get the same issue, for example, if we
try to destroy a stream from one of the stream's callback functions.]</i></p>
<hr>
<a name="471"><h3>471.&nbsp;result of what() implementation-defined</h3></a><p><b>Section:</b>&nbsp;18.6.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-support.html#lib.exception"> [lib.exception]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;28 Jun 2004</p>
<p>[lib.exception] specifies the following:</p>
<pre> exception (const exception&amp;) throw();
exception&amp; operator= (const exception&amp;) throw();
-4- Effects: Copies an exception object.
-5- Notes: The effects of calling what() after assignment
are implementation-defined.
</pre>
<p>
First, does the Note only apply to the assignment operator? If so,
what are the effects of calling what() on a copy of an object? Is
the returned pointer supposed to point to an identical copy of
the NTBS returned by what() called on the original object or not?
</p>
<p>
Second, is this Note intended to extend to all the derived classes
in section 19? I.e., does the standard provide any guarantee for
the effects of what() called on a copy of any of the derived class
described in section 19?
</p>
<p>
Finally, if the answer to the first question is no, I believe it
constitutes a defect since throwing an exception object typically
implies invoking the copy ctor on the object. If the answer is yes,
then I believe the standard ought to be clarified to spell out
exactly what the effects are on the copy (i.e., after the copy
ctor was called).
</p>
<p><i>[Redmond: Yes, this is fuzzy. The issue of derived classes is
fuzzy too.]</i></p>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="472"><h3>472.&nbsp;Missing "Returns" clause in std::equal_range</h3></a><p><b>Section:</b>&nbsp;25.3.3.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.equal.range"> [lib.equal.range]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a>&nbsp; <b>Submitter:</b>&nbsp;Prateek R Karandikar&nbsp; <b>Date:</b>&nbsp;29 Feb 1900</p>
<p>
There is no "Returns:" clause for std::equal_range, which returns non-void.
</p>
<p><b>Proposed resolution:</b></p>
<p>In 25.3.3.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.equal.range"> [lib.equal.range]</a>, change</p>
<blockquote>
<b>Effects:</b> Finds the largest subrange [i, j)...
</blockquote>
<p>to</p>
<blockquote>
<b>Returns:</b> The largest subrange [i, j)...
</blockquote>
<hr>
<a name="473"><h3>473.&nbsp;underspecified ctype calls</h3></a><p><b>Section:</b>&nbsp;22.2.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.locale.ctype"> [lib.locale.ctype]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;1 Jul 2004</p>
<p>
Most ctype member functions come in two forms: one that operates
on a single character at a time and another form that operates
on a range of characters. Both forms are typically described by
a single Effects and/or Returns clause.
</p>
<p>
The Returns clause of each of the single-character non-virtual forms
suggests that the function calls the corresponding single character
virtual function, and that the array form calls the corresponding
virtual array form. Neither of the two forms of each virtual member
function is required to be implemented in terms of the other.
</p>
<p>
There are three problems:
</p>
<p>
1. One is that while the standard does suggest that each non-virtual
member function calls the corresponding form of the virtual function,
it doesn't actually explicitly require it.
</p>
<p>
Implementations that cache results from some of the virtual member
functions for some or all values of their arguments might want to
call the array form from the non-array form the first time to fill
the cache and avoid any or most subsequent virtual calls. Programs
that rely on each form of the virtual function being called from
the corresponding non-virtual function will see unexpected behavior
when using such implementations.
</p>
<p>
2. The second problem is that either form of each of the virtual
functions can be overridden by a user-defined function in a derived
class to return a value that is different from the one produced by
the virtual function of the alternate form that has not been
overriden.
</p>
<p>
Thus, it might be possible for, say, ctype::widen(c) to return one
value, while for ctype::widen(&amp;c, &amp;c + 1, &amp;wc) to set
wc to another value. This is almost certainly not intended. Both
forms of every function should be required to return the same result
for the same character, otherwise the same program using an
implementation that calls one form of the functions will behave
differently than when using another implementation that calls the
other form of the function "under the hood."
</p>
<p>
3. The last problem is that the standard text fails to specify whether
one form of any of the virtual functions is permitted to be implemented
in terms of the other form or not, and if so, whether it is required
or permitted to call the overridden virtual function or not.
</p>
<p>
Thus, a program that overrides one of the virtual functions so that
it calls the other form which then calls the base member might end
up in an infinite loop if the called form of the base implementation
of the function in turn calls the other form.
</p>
<p><b>Proposed resolution:</b></p>
<p>
To fix these problems I propose the following:
</p>
<p>
Add two paragraphs immediately after 22.2.1.1 [lib.locale.ctype],
p2, with the following text:
</p>
<pre> -3- Each ctype non-virtual member function that comes in two forms,
one that takes a range of elements of char_type, and another
that takes just a single element of char_type, is required to
call the corresponding form of the virtual member function
with the same value of char_type to obtain the result. The
result for the same argument may be cached and returned from
subsequent calls to either form of the non-virtual member
function with that argument.
-4- For each ctype virtual member function that comes in two forms
(as explained above), the single element form is required to
produce the same result for a character c that the corresponding
array form produces for the array element with the same value as
c, and vice versa.
-5- It is unspecified whether the array form of each virtual member
function calls the single-element virtual overload of the same
function in a loop, or whether the single element form calls
the array form with an array of a single element with the value
of its argument, or whether neither form calls the other. In
any case, an implementation is not permitted to make calls from
one form of any virtual member function to the corresponding
other form that is overridden in a derived class.
</pre>
<hr>
<a name="474"><h3>474.&nbsp;confusing Footnote 297</h3></a><p><b>Section:</b>&nbsp;27.6.2.5.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.ostream.inserters.character"> [lib.ostream.inserters.character]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Martin Sebor&nbsp; <b>Date:</b>&nbsp;1 Jul 2004</p>
<p>
I think Footnote 297 is confused. The paragraph it applies to seems
quite clear in that widen() is only called if the object is not a char
stream (i.e., not basic_ostream&lt;char&gt;), so it's irrelevant what the
value of widen(c) is otherwise.
</p>
<p><b>Proposed resolution:</b></p>
<p>
I propose to strike the Footnote.
</p>
<hr>
<a name="475"><h3>475.&nbsp;May the function object passed to for_each modify the elements of the iterated sequence?</h3></a><p><b>Section:</b>&nbsp;25.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.foreach"> [lib.alg.foreach]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Stephan T. Lavavej, Jaakko Jarvi&nbsp; <b>Date:</b>&nbsp;9 Jul 2004</p>
<p>
It is not clear whether the function object passed to for_each is allowed to
modify the elements of the sequence being iterated over.
</p>
<p>
for_each is classified without explanation in [lib.alg.nonmodifying], "25.1
Non-modifying sequence operations". 'Non-modifying sequence operation' is
never defined.
</p>
<p>
25(5) says: "If an algorithm's Effects section says that a value pointed to
by any iterator passed as an argument is modified, then that algorithm has
an additional type requirement: The type of that argument shall satisfy the
requirements of a mutable iterator (24.1)."
</p>
<p>for_each's Effects section does not mention whether arguments can be
modified:</p>
<blockquote>
"Effects: Applies f to the result of dereferencing every iterator in the
range [first, last), starting from first and proceeding to last - 1."
</blockquote>
<p>
Every other algorithm in [lib.alg.nonmodifying] is "really" non-modifying in
the sense that neither the algorithms themselves nor the function objects
passed to the algorithms may modify the sequences or elements in any way.
This DR affects only for_each.
</p>
<p>
We suspect that for_each's classification in "non-modifying sequence
operations" means that the algorithm itself does not inherently modify the
sequence or the elements in the sequence, but that the function object
passed to it may modify the elements it operates on.
</p>
<p>
The original STL document by Stepanov and Lee explicitly prohibited the
function object from modifying its argument.
The "obvious" implementation of for_each found in several standard library
implementations, however, does not impose this restriction.
As a result, we suspect that the use of for_each with function objects that modify
their arguments is wide-spread.
If the restriction was reinstated, all such code would become non-conforming.
Further, none of the other algorithms in the Standard
could serve the purpose of for_each (transform does not guarantee the order in
which its function object is called).
</p>
<p>
We suggest that the standard be clarified to explicitly allow the function object
passed to for_each modify its argument.</p>
<p><b>Proposed resolution:</b></p>
<p>Add the following sentence to the Effects in 25.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.foreach"> [lib.alg.foreach]</a>:</p>
<blockquote>
"f may apply non-constant functions through the dereferenced iterators
passed to it; if it does, the type of first shall satisfy the requirements
of a mutable iterator (24.1)."
</blockquote>
<hr>
<a name="476"><h3>476.&nbsp;Forward Iterator implied mutability</h3></a><p><b>Section:</b>&nbsp;24.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Dave Abrahams&nbsp; <b>Date:</b>&nbsp;9 Jul 2004</p>
<p>24.1/3 says:</p>
<blockquote>
Forward iterators satisfy all the requirements of the input and
output iterators and can be used whenever either kind is specified
</blockquote>
<p>
The problem is that satisfying the requirements of output iterator
means that you can always assign *something* into the result of
dereferencing it. That makes almost all non-mutable forward
iterators non-conforming. I think we need to sever the refinement
relationship between forward iterator and output iterator.
</p>
<p><b>Proposed resolution:</b></p>
<p>in 24.1/3, replace:</p>
<blockquote>
Forward iterators satisfy all the requirements of the input and
output iterators and can be used whenever either kind is specified.
</blockquote>
<p>with</p>
<blockquote>
A forward iterator satisfies all the input iterator requirements.
A mutable forward iterator satisfies all the output iterator
requirements.
</blockquote>
<hr>
<a name="477"><h3>477.&nbsp;Operator-&gt; for const forward iterators</h3></a><p><b>Section:</b>&nbsp;24.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Dave Abrahams&nbsp; <b>Date:</b>&nbsp;11 Jul 2004</p>
<p>
The Forward Iterator requirements table contains the following:
</p>
<pre> expression return type operational precondition
semantics
========== ================== =========== ==========================
a-&gt;m U&amp; if X is mutable, (*a).m pre: (*a).m is well-defined.
otherwise const U&amp;
r-&gt;m U&amp; (*r).m pre: (*r).m is well-defined.
</pre>
<p>
The first line is exactly right. The second line is wrong. Basically
it implies that the const-ness of the iterator affects the const-ness
of referenced members. But Paragraph 11 of [lib.iterator.requirements] says:
</p>
<blockquote>
In the following sections, a and b denote values of type const X, n
denotes a value of the difference type Distance, u, tmp, and m
denote identifiers, r denotes a value of X&amp;, t denotes a value of
value type T, o denotes a value of some type that is writable to
the output iterator.
</blockquote>
<p>AFAICT if we need the second line at all, it should read the same
as the first line.</p>
<p>Related issue: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#478">478</a></p>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="478"><h3>478.&nbsp;Should forward iterator requirements table have a line for r-&gt;m?</h3></a><p><b>Section:</b>&nbsp;24.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Dave Abrahams&nbsp; <b>Date:</b>&nbsp;11 Jul 2004</p>
<p>
The Forward Iterator requirements table contains the following:
</p>
<pre> expression return type operational precondition
semantics
========== ================== =========== ==========================
a-&gt;m U&amp; if X is mutable, (*a).m pre: (*a).m is well-defined.
otherwise const U&amp;
r-&gt;m U&amp; (*r).m pre: (*r).m is well-defined.
</pre>
<p>The second line may be unnecessary. Paragraph 11 of
[lib.iterator.requirements] says:
</p>
<blockquote>
In the following sections, a and b denote values of type const X, n
denotes a value of the difference type Distance, u, tmp, and m
denote identifiers, r denotes a value of X&amp;, t denotes a value of
value type T, o denotes a value of some type that is writable to
the output iterator.
</blockquote>
<p>
Because operators can be overloaded on an iterator's const-ness, the
current requirements allow iterators to make many of the operations
specified using the identifiers a and b invalid for non-const
iterators. Rather than expanding the tables, I think the right
answer is to change
</p>
<blockquote>
"const X"
</blockquote>
<p> to </p>
<blockquote>
"X or const X"
</blockquote>
<p>in paragraph 11 of [lib.iterator.requirements].</p>
<p>Related issue: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#477">477</a></p>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="479"><h3>479.&nbsp;Container requirements and placement new</h3></a><p><b>Section:</b>&nbsp;23.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Herb Sutter&nbsp; <b>Date:</b>&nbsp;1 Aug 2004</p>
<p>Nothing in the standard appears to make this program ill-formed:</p>
<pre> struct C {
void* operator new( size_t s ) { return ::operator new( s ); }
// NOTE: this hides in-place and nothrow new
};
int main() {
vector&lt;C&gt; v;
v.push_back( C() );
}
</pre>
<p>Is that intentional? We should clarify whether or not we intended
to require containers to support types that define their own special
versions of <tt>operator new</tt>.</p>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="480"><h3>480.&nbsp;unary_function and binary_function should have protected nonvirtual destructors</h3></a><p><b>Section:</b>&nbsp;20.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.base"> [lib.base]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Joe Gottman&nbsp; <b>Date:</b>&nbsp;19 Aug 2004</p>
<p>The classes std::unary_function and std::binary_function are both
designed to be inherited from but contain no virtual functions. This
makes it too easy for a novice programmer to write code like
binary_function&lt;int, int, int&gt; *p = new plus&lt;int&gt;; delete p;</p>
<p>There are two common ways to prevent this source of undefined
behavior: give the base class a public virtual destructor, or give it
a protected nonvirtual destructor. Since unary_function and
binary_function have no other virtual functions, (note in particular
the absence of an operator()() ), it would cost too much to give them
public virtual destructors. Therefore, they should be given protected
nonvirtual destructors.</p>
<p><b>Proposed resolution:</b></p>
<p>Change Paragraph 20.3.1 of the Standard from</p>
<pre> template &lt;class Arg, class Result&gt;
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
};
template &lt;class Arg1, class Arg2, class Result&gt;
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
</pre>
<p>to</p>
<pre> template &lt;class Arg, class Result&gt;
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
protected:
~unary_function() {}
};
template &lt;class Arg1, class Arg2, class Result&gt;
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
protected:
~binary_function() {}
};
</pre>
<hr>
<a name="481"><h3>481.&nbsp;unique's effects on the range [result, last)</h3></a><p><b>Section:</b>&nbsp;25.2.8 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.unique"> [lib.alg.unique]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Andrew Koenig&nbsp; <b>Date:</b>&nbsp;30 Aug 2004</p>
<p>
The standard says that unique(first, last) "eliminates all but the
first element from every consecutive group of equal elements" in
[first, last) and returns "the end of the resulting range". So a
postcondition is that [first, result) is the same as the old [first,
last) except that duplicates have been eliminated.
</p>
<p>What postconditions are there on the range [result, last)? One
might argue that the standard says nothing about those values, so
they can be anything. One might also argue that the standard
doesn't permit those values to be changed, so they must not be.
Should the standard say something explicit one way or the other?</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<hr>
<a name="482"><h3>482.&nbsp;Swapping pairs</h3></a><p><b>Section:</b>&nbsp;20.2.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.pairs"> [lib.pairs]</a>, 25.2.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.swap"> [lib.alg.swap]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Andrew Koenig&nbsp; <b>Date:</b>&nbsp;14 Sep 2004</p>
<p>(Based on recent comp.std.c++ discussion)</p>
<p>Pair (and tuple) should specialize std::swap to work in terms of
std::swap on their components. For example, there's no obvious reason
why swapping two objects of type pair&lt;vector&lt;int&gt;,
list&lt;double&gt; &gt; should not take O(1).</p>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="484"><h3>484.&nbsp;Convertible to T</h3></a><p><b>Section:</b>&nbsp;24.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.input.iterators"> [lib.input.iterators]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Chris&nbsp; <b>Date:</b>&nbsp;16 Sep 2004</p>
<p>From comp.std.c++:</p>
<p>
I note that given an input iterator a for type T,
then *a only has to be "convertable to T", not actually of type T.
</p>
<p>Firstly, I can't seem to find an exact definition of "convertable to T".
While I assume it is the obvious definition (an implicit conversion), I
can't find an exact definition. Is there one?</p>
<p>Slightly more worryingly, there doesn't seem to be any restriction on
the this type, other than it is "convertable to T". Consider two input
iterators a and b. I would personally assume that most people would
expect *a==*b would perform T(*a)==T(*b), however it doesn't seem that
the standard requires that, and that whatever type *a is (call it U)
could have == defined on it with totally different symantics and still
be a valid inputer iterator.</p>
<p>Is this a correct reading? When using input iterators should I write
T(*a) all over the place to be sure that the object i'm using is the
class I expect?</p>
<p>This is especially a nuisance for operations that are defined to be
"convertible to bool". (This is probably allowed so that
implementations could return say an int and avoid an unnessary
conversion. However all implementations I have seen simply return a
bool anyway. Typical implemtations of STL algorithms just write
things like <tt>while(a!=b &amp;&amp; *a!=0)</tt>. But strictly
speaking, there are lots of types that are convertible to T but
that also overload the appropriate operators so this doesn't behave
as expected.</p>
<p>If we want to make code like this legal (which most people seem to
expect), then we'll need to tighten up what we mean by "convertible
to T".</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<hr>
<a name="485"><h3>485.&nbsp;output iterator insufficently constrained</h3></a><p><b>Section:</b>&nbsp;24.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.output.iterators"> [lib.output.iterators]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Chris&nbsp; <b>Date:</b>&nbsp;13 Oct 2004</p>
<p>
The note on 24.1.2 Output iterators insufficently limits what can be
performed on output iterators. While it requires that each iterator is
progressed through only once and that each iterator is written to only
once, it does not require the following things:</p>
<p>Note: Here it is assumed that x is an output iterator of type X which
has not yet been assigned to.</p>
<p>a) That each value of the output iterator is written to:
The standard allows:
++x; ++x; ++x;
</p>
<p>
b) That assignments to the output iterator are made in order
X a(x); ++a; *a=1; *x=2; is allowed
</p>
<p>
c) Chains of output iterators cannot be constructed:
X a(x); ++a; X b(a); ++b; X c(b); ++c; is allowed, and under the current
wording (I believe) x,a,b,c could be written to in any order.
</p>
<p>I do not believe this was the intension of the standard?</p>
<p><b>Proposed resolution:</b></p>
<p>Add to the note:</p>
<p>"The values of an output iterator must be assigned to in the order they
are generated. It is undefined to progress forward more than once from a
value of an output iterator which has not yet been assigned."</p>
<p>This is I believe the intension of the existing text. The "progress
forward once" is allowed so that "*r++=t" is allowed. It may be prefered
to instead allow something more along the lines of:</p>
<p>"The values of an output iterator must be assigned to in the order they
are generated. With the exception of '*r++=t', an iterator must always
be assigned to before it is incremented".</p>
<hr>
<a name="487"><h3>487.&nbsp;Allocator::construct is too limiting</h3></a><p><b>Section:</b>&nbsp;20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Dhruv Matani&nbsp; <b>Date:</b>&nbsp;17 Oct 2004</p>
<p>
The standard's version of allocator::construct(pointer,
const_reference) severely limits what you can construct using this
function. Say you can construct a socket from a file descriptor. Now,
using this syntax, I first have to manually construct a socket from
the fd, and then pass the constructed socket to the construct()
function so it will just to an uninitialized copy of the socket I
manually constructed. Now it may not always be possible to copy
construct a socket eh! So, I feel that the changes should go in the
allocator::construct(), making it:
</p>
<pre> template&lt;typename T&gt;
struct allocator{
template&lt;typename T1&gt;
void construct(pointer T1 const&amp; rt1);
};
</pre>
<p>
Now, the ctor of the class T which matches the one that takes a T1 can
be called! Doesn't that sound great?
</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<hr>
<a name="488"><h3>488.&nbsp;rotate throws away useful information</h3></a><p><b>Section:</b>&nbsp;25.2.10 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.rotate"> [lib.alg.rotate]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Howard Hinnant&nbsp; <b>Date:</b>&nbsp;22 Nov 2004</p>
<p>
rotate takes 3 iterators: first, middle and last which point into a
sequence, and rearranges the sequence such that the subrange [middle,
last) is now at the beginning of the sequence and the subrange [first,
middle) follows. The return type is void.
</p>
<p>
In many use cases of rotate, the client needs to know where the
subrange [first, middle) starts after the rotate is performed. This
might look like:
</p>
<pre> rotate(first, middle, last);
Iterator i = advance(first, distance(middle, last));
</pre>
<p>
Unless the iterators are random access, the computation to find the
start of the subrange [first, middle) has linear complexity. However,
it is not difficult for rotate to return this information with
negligible additional computation expense. So the client could code:
</p>
<pre> Iterator i = rotate(first, middle, last);
</pre>
<p>
and the resulting program becomes significantly more efficient.
</p>
<p>
While the backwards compatibility hit with this change is not zero, it
is very small (similar to that of lwg <ire ref="130"></ire>), and there is
a significant benefit to the change.
</p>
<p><b>Proposed resolution:</b></p>
<p>In 25p2, change:</p>
<pre> template&lt;class ForwardIterator&gt;
void rotate(ForwardIterator first, ForwardIterator middle,
ForwardIterator last);
</pre>
<p>to:</p>
<pre> template&lt;class ForwardIterator&gt;
ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
ForwardIterator last);
</pre>
<p>In 25.2.10, change:</p>
<pre> template&lt;class ForwardIterator&gt;
void rotate(ForwardIterator first, ForwardIterator middle,
ForwardIterator last);
</pre>
<p>to:</p>
<pre> template&lt;class ForwardIterator&gt;
ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
ForwardIterator last);
</pre>
<p>In 25.2.10 insert a new paragraph after p1:</p>
<blockquote>
<p><b>Returns</b>: advance(first, distance(middle, last)).</p>
</blockquote>
<hr>
<a name="489"><h3>489.&nbsp;std::remove / std::remove_if wrongly specified</h3></a><p><b>Section:</b>&nbsp;25.2.7 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.remove"> [lib.alg.remove]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Thomas Mang&nbsp; <b>Date:</b>&nbsp;12 Dec 2004</p>
<p>In Section 25.2.7 [lib.alg.remove], paragraphs 1 to 5 describe the
behavior of the mutating sequence operations std::remove and
std::remove_if. However, the wording does not reflect the intended
behavior [Note: See definition of intended behavior below] of these
algorithms, as it is known to the C++ community [1].
</p>
<p>1) Analysis of current wording:</p>
<p>25.2.7 [lib.alg.remove], paragraph 2:</p>
<p>Current wording says:
"Effects: Eliminates all the elements referred to by iterator i in the
range [first, last) for which the following corresponding conditions
hold: *i == value, pred(*i) != false."</p>
<p>
This sentences expresses specifically that all elements denoted by the
(original) range [first, last) for which the corresponding condition
hold will be eliminated. Since there is no formal definition of the term
"eliminate" provided, the meaning of "eliminate" in everyday language
implies that as postcondition, no element in the range denoted by
[first, last) will hold the corresponding condition on reiteration over
the range [first, last).
</p>
<p>
However, this is neither the intent [Note: See definition of intended
behavior below] nor a general possible approach. It can be easily proven
that if all elements of the original range[first, last) will hold the
condition, it is not possible to substitute them by an element for which
the condition will not hold.
</p>
<p>25.2.7 [lib.alg.remove], paragraph 3:</p>
<p>
Current wording says:
"Returns: The end of the resulting range."
</p>
<p>
The resulting range is not specified. In combination with 25.2.7
[lib.alg.remove], paragraph 2, the only reasonable interpretation of
this so-called resulting range is the range [first,last) - thus
returning always the ForwardIterator 'last' parameter.
</p>
<p>
25.2.7 [lib.alg.remove], paragraph 4:
</p>
<p>
Current wording says:
"Notes: Stable: the relative order of the elements that are not removed
is the same as their relative order in the original range"
</p>
<p>
This sentences makes use of the term "removed", which is neither
specified, nor used in a previous paragraph (which uses the term
"eliminate"), nor unamgiuously separated from the name of the algorithm.
</p>
<p>2) Description of intended behavior:</p>
<p>
For the rest of this Defect Report, it is assumed that the intended
behavior was that all elements of the range [first, last) which do not
hold the condition *i == value (std::remove) or pred(*i) != false
(std::remove_if)], call them s-elements [Note: s...stay], will be placed
into a contiguous subrange of [first, last), denoted by the iterators
[first, return value). The number of elements in the resulting range
[first, return value) shall be equal to the number of s-elements in the
original range [first, last). The relative order of the elements in the
resulting subrange[first, return value) shall be the same as the
relative order of the corresponding elements in the original range. It
is undefined whether any elements in the resulting subrange [return
value, last) will hold the corresponding condition, or not.
</p>
<p>
All implementations known to the author of this Defect Report comply
with this intent. Since the intent of the behavior (contrary to the
current wording) is also described in various utility references serving
the C++ community [1], it is not expected that fixing the paragraphs
will influence current code - unless the code relies on the behavior as
it is described by current wording and the implementation indeed
reflects the current wording, and not the intent.
</p>
<p>3) Proposed fixes:</p>
<p>Change 25.2.7 [lib.alg.remove], paragraph 2 to:</p>
<p>
"Effect: Places all the elements referred to by iterator i in the range
[first, last) for which the following corresponding conditions hold :
!(*i == value), pred(*i) == false into the subrange [first, k) of the
original range, where k shall denote a value of type ForwardIterator. It
is undefined whether any elements in the resulting subrange [k, last)
will hold the corresponding condition, or not."
</p>
<p>Comments to the new wording:</p>
<p>
a) "Places" has no special meaning, and the everyday language meaning
should fit.
b) The corresponding conditions were negated compared to the current
wording, becaue the new wording requires it.
c) The wording "of the original range" might be redundant, since any
subrange starting at 'first' and containing no more elements than the
original range is implicitly a subrange of the original range [first,
last).
d) The iterator k was introduced instead of "return value" in order to
avoid a cyclic dependency on 25.2.7/3. The wording ", where k shall
denote a value of type ForwardIterator" might be redundant, because it
follows implicitly by 25.2.7/3.
e) "Places" does, in the author's opinion, explicitly forbid duplicating
any element holding the corresponding condition in the original range
[first, last) within the resulting range [first, k). If there is doubt
this term might be not unambiguous regarding this, it is suggested that
k is specified more closely by the following wording: "k shall denote a
value of type ForwardIterator [Note: see d)] so that k - first is equal
to the number of elements in the original range [first, last) for which
the corresponding condition did hold". This could also be expressed as a
separate paragraph "Postcondition:"
f) The senctence "It is undefined whether any elements in the resulting
subrange [k, last) will hold the corresponding condition, or not." was
added consciously so the term "Places" does not imply if the original
range [first, last) contains n elements holding the corresponding
condition, the identical range[first, last) will also contain exactly n
elements holding the corresponding condition after application of the
algorithm.
</p>
<p>
Change 25.2.7 [lib.alg.remove], paragraph 3 to:
"Returns: The iterator k."
</p>
<p>
Change 25.2.7 [lib.alg.remove], paragraph 4 to:
"Notes: Stable: the relative order of the elements that are placed into
the subrange [first, return value) shall be the same as their relative
order was in the original range [first, last) prior to application of
the algorithm."
</p>
<p>
Comments to the new wording:
</p>
<p>
a) the wording "was ... prior to application of the algorithm" is used
to explicitly distinguish the original range not only by means of
iterators, but also by a 'chronological' factor from the resulting range
[first, return value). It might be redundant.
</p>
<p>
[1]:
The wording of these references is not always unambiguous, and provided
examples partially contradict verbal description of the algorithms,
because the verbal description resembles the problematic wording of
ISO/IEC 14882:2003.
</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<hr>
<a name="490"><h3>490.&nbsp;std::unique wrongly specified</h3></a><p><b>Section:</b>&nbsp;25.2.8 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.unique"> [lib.alg.unique]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Thomas Mang&nbsp; <b>Date:</b>&nbsp;12 Dec 2004</p>
<p>In Section 25.2.8 [lib.alg.unique], paragraphs 1 to 3 describe the
behavior of the mutating sequence operation std::unique. However, the
wording does not reflect the intended behavior [Note: See definition of
intended behavior below] of these algorithms, as it is known to the C++
community [1].</p>
<p>1) Analysis of current wording:</p>
<p>25.2.8 [lib.alg.unique], paragraph 1:</p>
<p>
Current wording says:
"Effects: Eliminates all but the first element from every consecutive
group of equal elements referred to by the iterator i in the range
[first, last) for which the following corresponding conditions hold: *i
== *(i - 1) or pred(*i, *(i -1)) != false"
</p>
<p>
This sentences expresses specifically that all elements denoted by the
(original) range [first, last) which are not but the first element from
a consecutive group of equal elements (where equality is defined as *i
== *(i - 1) or pred(*i, *(i - 1)) ! = false) [Note: See DR 202], call
them r-elements [Note: r...remove], will be eliminated. Since there is
no formal definition of the term "eliminate" provided, it is undefined
how this "elimination" takes place. But the meaning of "eliminate" in
everyday language seems to disallow explicitly that after application of
the algorithm, any r-element will remain at any position of the range
[first, last) [2].
</p>
<p>
Another defect in the current wording concerns the iterators used to
compare two elements for equality: The current wording contains the
expression "(i - 1)", which is not covered by 25/9 [Note: See DR
submitted by Thomas Mang regarding invalid iterator arithmetic
expressions].
</p>
<p>
25.2.8 [lib.alg.unique], paragraph 2:
</p>
<p>Current wording says:
"Returns: The end of the resulting range."</p>
<p>
The resulting range is not specified. In combination with 25.2.8
[lib.alg.unique], paragraph 1, one reasonable interpretation (in the
author's opinion even the only possible interpretation) of this
so-called resulting range is the range [first, last) - thus returning
always the ForwardIterator 'last' parameter.
</p>
<p>2) Description of intended behavior:</p>
<p>
For the rest of this Defect Report, it is assumed that the intended
behavior was that all elements denoted by the original range [first,
last) which are the first element from a consecutive group of elements
for which the corresponding conditions: *(i-1) == *i (for the version of
unique without a predicate argument) or pred(*(i-1), *i) ! = false (for
the version of unique with a predicate argument) [Note: If such a group
of elements consists of only a single element, this is also considered
the first element] [Note: See resolutions of DR 202], call them
s-elements [Note: s...stay], will be placed into a contiguous subrange
of [first, last), denoted by the iterators [first, return value). The
number of elements in the resulting range [first, return value) shall be
equal to the number of s-elements in the original range [first, last).
Invalid iterator arithmetic expressions are expected to be resolved as
proposed in DR submitted by Thomas Mang regarding invalid iterator
arithmetic expressions. It is also assumed by the author that the
relative order of the elements in the resulting subrange [first, return
value) shall be the same as the relative order of the corresponding
elements (the s-elements) in the original range [Note: If this was not
intended behavior, the additional proposed paragraph about stable order
will certainly become obsolete].
Furthermore, the resolutions of DR 202 are partially considered.
</p>
<p>
All implementations known to the author of this Defect Report comply
with this intent [Note: Except possible effects of DR 202]. Since this
intent of the behavior (contrary to the current wording) is also
described in various utility references serving the C++ community [1],
it is not expected that fixing the paragraphs will influence current
code [Note: Except possible effects of DR 202] - unless the code relies
on the behavior as it is described by current wording and the
implementation indeed reflects the current wording, and not the intent.
</p>
<p>3) Proposed fixes:</p>
<p>
Change 25.2.8 [lib.alg.unique], paragraph 1 to:
</p>
<p>
"Effect: Places the first element from every consecutive group of
elements, referred to by the iterator i in the range [first, last), for
which the following conditions hold: *(i-1) == *i (for the version of
unique without a predicate argument) or pred(*(i -1), *i) != false (for
the version of unique with a predicate argument), into the subrange
[first, k) of the original range, where k shall denote a value of type
ForwardIterator."
</p>
<p>Comments to the new wording:</p>
<p>
a) The new wording was influenced by the resolutions of DR 202. If DR
202 is resolved in another way, the proposed wording need also
additional review.
b) "Places" has no special meaning, and the everyday language meaning
should fit.
c) The expression "(i - 1)" was left, but is expected that DR submitted
by Thomas Mang regarding invalid iterator arithmetic expressions will
take this into account.
d) The wording "(for the version of unique without a predicate
argument)" and "(for the version of unique with a predicate argument)"
was added consciously for clarity and is in resemblence with current
23.2.2.4 [lib.list.ops], paragraph 19. It might be considered redundant.
e) The wording "of the original range" might be redundant, since any
subrange starting at first and containing no more elements than the
original range is implicitly a subrange of the original range [first,
last).
f) The iterator k was introduced instead of "return value" in order to
avoid a cyclic dependency on 25.2.8 [lib.alg.unique], paragraph 2. The
wording ", where k shall denote a value of type ForwardIterator" might
be redundant, because it follows implicitly by 25.2.8 [lib.alg.unique],
paragraph 2.
g) "Places" does, in the author's opinion, explicitly forbid duplicating
any s-element in the original range [first, last) within the resulting
range [first, k). If there is doubt this term might be not unambiguous
regarding this, it is suggested that k is specified more closely by the
following wording: "k shall denote a value of type ForwardIterator
[Note: See f)] so that k - first is equal to the number of elements in
the original range [first, last) being the first element from every
consecutive group of elements for which the corresponding condition did
hold". This could also be expressed as a separate paragraph
"Postcondition:".
h) If it is considered that the wording is unclear whether it declares
the element of a group which consists of only a single element
implicitly to be the first element of this group [Note: Such an
interpretation could eventually arise especially in case last - first ==
1] , the following additional sentence is proposed: "If such a group of
elements consists of only a single element, this element is also
considered the first element."
</p>
<p>
Change 25.2.8 [lib.alg.unique], paragraph 2 to:
"Returns: The iterator k."
</p>
<p>
Add a separate paragraph "Notes:" as 25.2.8 [lib.alg.unique], paragraph
2a or 3a, or a separate paragraph "Postcondition:" before 25.2.8
[lib.alg.unique], paragraph 2 (wording inside {} shall be eliminated if
the preceding expressions are used, or the preceding expressions shall
be eliminated if wording inside {} is used):
</p>
<p>
"Notes:{Postcondition:} Stable: the relative order of the elements that
are placed into the subrange [first, return value {k}) shall be the same
as their relative order was in the original range [first, last) prior to
application of the algorithm."
</p>
<p>Comments to the new wording:</p>
<p>
a) It is assumed by the author that the algorithm was intended to be
stable.
In case this was not the intent, this paragraph becomes certainly
obsolete.
b) The wording "was ... prior to application of the algorithm" is used
to explicitly distinguish the original range not only by means of
iterators, but also by a 'chronological' factor from the resulting range
[first, return value). It might be redundant.
</p>
<p>
25.2.8 [lib.alg.unique], paragraph 3:
</p>
<p>See DR 239.</p>
<p>
4) References to other DRs:
</p>
<p>
See DR 202, but which does not address any of the problems described in
this Defect Report [Note: This DR is supposed to complement DR 202].
See DR 239.
See DR submitted by Thomas Mang regarding invalid iterator arithmetic
expressions.
</p>
<p>
[1]:
The wording of these references is not always unambiguous, and provided
examples partially contradict verbal description of the algorithms,
because the verbal description resembles the problematic wording of
ISO/IEC 14882:2003.
</p>
<p>
[2]:
Illustration of conforming implementations according to current wording:
</p>
<p>
One way the author of this DR considers how this "elimination" could be
achieved by a conforming implementation according to current wording is
by substituting each r-element by _any_ s-element [Note: s...stay; any
non-r-element], since all r-elements are "eliminated".
</p>
<p>
In case of a sequence consisting of elements being all 'equal' [Note:
See DR 202], substituting each r-element by the single s-element is the
only possible solution according to current wording.
</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<hr>
<a name="491"><h3>491.&nbsp;std::list&lt;&gt;::unique incorrectly specified</h3></a><p><b>Section:</b>&nbsp;23.2.2.4 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.list.ops"> [lib.list.ops]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Thomas Mang&nbsp; <b>Date:</b>&nbsp;12 Dec 2004</p>
<p>In Section 23.2.2.4 [lib.list.ops], paragraphs 19 to 21 describe the
behavior of the std::list&lt;T, Allocator&gt;::unique operation. However, the
current wording is defective for various reasons.</p>
<p>
1) Analysis of current wording:
</p>
<p>23.2.2.4 [lib.list.ops], paragraph 19:</p>
<p>
Current wording says:
"Effects: Eliminates all but the first element from every consecutive
group of equal elements referred to by the iterator i in the range
[first + 1, last) for which *i == *(i - 1) (for the version of unique
with no argument) or pred(*i, *(i -1)) (for the version of unique with a
predicate argument) holds."</p>
<p>
This sentences makes use of the undefined term "Eliminates". Although it
is, to a certain degree, reasonable to consider the term "eliminate"
synonymous with "erase", using "Erase" in the first place, as the
wording of 23.2.2.4 [lib.list.ops], paragraph 15 does, would be clearer.</p>
<p>
The range of the elements referred to by iterator i is "[first + 1,
last)". However, neither "first" nor "last" is defined.</p>
<p>
The sentence makes three times use of iterator arithmetic expressions (
"first + 1", "*i == *(i - 1)", "pred(*i, *(i -1))" ) which is not
defined for bidirectional iterator [see DR submitted by Thomas Mang
regarding invalid iterator arithmetic expressions].</p>
<p>
The same problems as pointed out in DR 202 (equivalence relation / order
of arguments for pred()) apply to this paragraph.</p>
<p>
23.2.2.4 [lib.list.ops], paragraph 20:
</p>
<p>
Current wording says:
"Throws: Nothing unless an exception in thrown by *i == *(i-1) or
pred(*i, *(i - 1))"</p>
<p>
The sentence makes two times use of invalid iterator arithmetic
expressions ( "*i == *(i - 1)", "pred(*i, *(i -1))" ).
</p>
<p>
[Note: Minor typos: "in" / missing dot at end of sentence.]
</p>
<p>
23.2.2.4 [lib.list.ops], paragraph 21:</p>
<p>
Current wording says:
"Complexity: If the range (last - first) is not empty, exactly (last -
first) - 1 applications of the corresponding predicate, otherwise no
application of the predicate.</p>
<p>
See DR 315 regarding "(last - first)" not yielding a range.</p>
<p>
Invalid iterator arithmetic expression "(last - first) - 1" left .</p>
<p>2) Description of intended behavior:</p>
<p>
For the rest of this Defect Report, it is assumed that "eliminate" is
supposed to be synonymous to "erase", that "first" is equivalent to an
iterator obtained by a call to begin(), "last" is equivalent to an
iterator obtained by a call to end(), and that all invalid iterator
arithmetic expressions are resolved as described in DR submitted by
Thomas Mang regarding invalid iterator arithmetic expressions.</p>
<p>
Furthermore, the resolutions of DR 202 are considered regarding
equivalence relation and order of arguments for a call to pred.</p>
<p>
All implementations known to the author of this Defect Report comply
with these assumptions, apart from the impact of the alternative
resolution of DR 202. Except for the changes implied by the resolutions
of DR 202, no impact on current code is expected.</p>
<p>
3) Proposed fixes:</p>
<p>
Change 23.2.2.4 [lib.list.ops], paragraph 19 to:</p>
<p>
"Effect: Erases all but the first element from every consecutive group
of elements, referred to by the iterator i in the range [begin(),
end()), for which the following conditions hold: *(i-1) == *i (for the
version of unique with no argument) or pred(*(i-1), *i) != false (for
the version of unique with a predicate argument)."</p>
<p>
Comments to the new wording:</p>
<p>
a) The new wording was influenced by DR 202 and the resolutions
presented there. If DR 202 is resolved in another way, the proposed
wording need also additional review.
b) "Erases" refers in the author's opinion unambiguously to the member
function "erase". In case there is doubt this might not be unamgibuous,
a direct reference to the member function "erase" is suggested [Note:
This would also imply a change of 23.2.2.4 [lib.list.ops], paragraph
15.].
c) The expression "(i - 1)" was left, but is expected that DR submitted
by Thomas Mang regarding invalid iterator arithmetic expressions will
take this into account.
d) The wording "(for the version of unique with no argument)" and "(for
the version of unique with a predicate argument)" was kept consciously
for clarity.
e) "begin()" substitutes "first", and "end()" substitutes "last". The
range need adjustment from "[first + 1, last)" to "[begin(), end())" to
ensure a valid range in case of an empty list.
f) If it is considered that the wording is unclear whether it declares
the element of a group which consists of only a single element
implicitly to be the first element of this group [Note: Such an
interpretation could eventually arise especially in case size() == 1] ,
the following additional sentence is proposed: "If such a group of
elements consists of only a single element, this element is also
considered the first element."</p>
<p>
Change 23.2.2.4 [lib.list.ops], paragraph 20 to:</p>
<p>
"Throws: Nothing unless an exception is thrown by *(i-1) == *i or
pred(*(i-1), *i)."</p>
<p>
Comments to the new wording:</p>
<p>
a) The wording regarding the conditions is identical to proposed
23.2.2.4 [lib.list.ops], paragraph 19. If 23.2.2.4 [lib.list.ops],
paragraph 19 is resolved in another way, the proposed wording need also
additional review.
b) The expression "(i - 1)" was left, but is expected that DR submitted
by Thomas Mang regarding invalid iterator arithmetic expressions will
take this into account.
c) Typos fixed.</p>
<p>
Change 23.2.2.4 [lib.list.ops], paragraph 21 to:</p>
<p>
"Complexity: If empty() == false, exactly size() - 1 applications of the
corresponding predicate, otherwise no applications of the corresponding
predicate."</p>
<p>
Comments to the new wording:</p>
<p>
a) The new wording is supposed to also replace the proposed resolution
of DR 315, which suffers from the problem of undefined "first" / "last".
</p>
<p>
5) References to other DRs:</p>
<p>See DR 202.
See DR 239.
See DR 315.
See DR submitted by Thomas Mang regarding invalid iterator arithmetic
expressions.</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<hr>
<a name="492"><h3>492.&nbsp;Invalid iterator arithmetic expressions</h3></a><p><b>Section:</b>&nbsp;23 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.containers"> [lib.containers]</a>, 24 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.iterators"> [lib.iterators]</a>, 25 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.algorithms"> [lib.algorithms]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Thomas Mang&nbsp; <b>Date:</b>&nbsp;12 Dec 2004</p>
<p>Various clauses other than clause 25 make use of iterator arithmetic not
supported by the iterator category in question.
Algorithms in clause 25 are exceptional because of 25 [lib.algorithms],
paragraph 9, but this paragraph does not provide semantics to the
expression "iterator - n", where n denotes a value of a distance type
between iterators.</p>
<p>1) Examples of current wording:</p>
<p>Current wording outside clause 25:</p>
<p>
23.2.2.4 [lib.list.ops], paragraphs 19-21: "first + 1", "(i - 1)",
"(last - first)"
23.3.1.1 [lib.map.cons], paragraph 4: "last - first"
23.3.2.1 [lib.multimap.cons], paragraph 4: "last - first"
23.3.3.1 [lib.set.cons], paragraph 4: "last - first"
23.3.4.1 [lib.multiset.cons], paragraph 4: "last - first"
24.4.1 [lib.reverse.iterators], paragraph 1: "(i - 1)"
</p>
<p>
[Important note: The list is not complete, just an illustration. The
same issue might well apply to other paragraphs not listed here.]</p>
<p>None of these expressions is valid for the corresponding iterator
category.</p>
<p>Current wording in clause 25:</p>
<p>
25.1.1 [lib.alg.foreach], paragraph 1: "last - 1"
25.1.3 [lib.alg.find.end], paragraph 2: "[first1, last1 -
(last2-first2))"
25.2.8 [lib.alg.unique], paragraph 1: "(i - 1)"
25.2.8 [lib.alg.unique], paragraph 5: "(i - 1)"
</p>
<p>
However, current wording of 25 [lib.algorithms], paragraph 9 covers
neither of these four cases:</p>
<p>Current wording of 25 [lib.algorithms], paragraph 9:</p>
<p>
"In the description of the algorithms operator + and - are used for some
of the iterator categories for which they do not have to be defined. In
these cases the semantics of a+n is the same as that of</p>
<pre>{X tmp = a;
advance(tmp, n);
return tmp;
}
</pre>
<p>and that of b-a is the same as of return distance(a, b)"</p>
<p>
This paragrpah does not take the expression "iterator - n" into account,
where n denotes a value of a distance type between two iterators [Note:
According to current wording, the expression "iterator - n" would be
resolved as equivalent to "return distance(n, iterator)"]. Even if the
expression "iterator - n" were to be reinterpreted as equivalent to
"iterator + -n" [Note: This would imply that "a" and "b" were
interpreted implicitly as values of iterator types, and "n" as value of
a distance type], then 24.3.4/2 interfers because it says: "Requires: n
may be negative only for random access and bidirectional iterators.",
and none of the paragraphs quoted above requires the iterators on which
the algorithms operate to be of random access or bidirectional category.
</p>
<p>2) Description of intended behavior:</p>
<p>
For the rest of this Defect Report, it is assumed that the expression
"iterator1 + n" and "iterator1 - iterator2" has the semantics as
described in current 25 [lib.algorithms], paragraph 9, but applying to
all clauses. The expression "iterator1 - n" is equivalent to an
result-iterator for which the expression "result-iterator + n" yields an
iterator denoting the same position as iterator1 does. The terms
"iterator1", "iterator2" and "result-iterator" shall denote the value of
an iterator type, and the term "n" shall denote a value of a distance
type between two iterators.</p>
<p>
All implementations known to the author of this Defect Report comply
with these assumptions.
No impact on current code is expected.</p>
<p>3) Proposed fixes:</p>
<p>Change 25 [lib.algorithms], paragraph 9 to:</p>
<p>
"In the description of the algorithms operator + and - are used for some
of the iterator categories for which they do not have to be defined. In
this paragraph, a and b denote values of an iterator type, and n denotes
a value of a distance type between two iterators. In these cases the
semantics of a+n is the same as that of</p>
<pre>{X tmp = a;
advance(tmp, n);
return tmp;
}
</pre>
<p>,the semantics of a-n denotes the value of an iterator i for which the
following condition holds:
advance(i, n) == a,
and that of b-a is the same as of
return distance(a, b)".
</p>
<p>Comments to the new wording:</p>
<p>
a) The wording " In this paragraph, a and b denote values of an iterator
type, and n denotes a value of a distance type between two iterators."
was added so the expressions "b-a" and "a-n" are distinguished regarding
the types of the values on which they operate.
b) The wording ",the semantics of a-n denotes the value of an iterator i
for which the following condition holds: advance(i, n) == a" was added
to cover the expression 'iterator - n'. The wording "advance(i, n) == a"
was used to avoid a dependency on the semantics of a+n, as the wording
"i + n == a" would have implied. However, such a dependency might well
be deserved.
c) DR 225 is not considered in the new wording.
</p>
<p>
Proposed fixes regarding invalid iterator arithmetic expressions outside
clause 25:</p>
<p>
Either
a) Move modified 25 [lib.algorithms], paragraph 9 (as proposed above)
before any current invalid iterator arithmetic expression. In that case,
the first sentence of 25 [lib.algorithms], paragraph 9, need also to be
modified and could read: "For the rest of this International Standard,
...." / "In the description of the following clauses including this
...." / "In the description of the text below ..." etc. - anyways
substituting the wording "algorithms", which is a straight reference to
clause 25.
In that case, 25 [lib.algorithms] paragraph 9 will certainly become
obsolete.
Alternatively,
b) Add an appropiate paragraph similar to resolved 25 [lib.algorithms],
paragraph 9, to the beginning of each clause containing invalid iterator
arithmetic expressions.
Alternatively,
c) Fix each paragraph (both current wording and possible resolutions of
DRs) containing invalid iterator arithmetic expressions separately.
</p>
<p>5) References to other DRs:</p>
<p>
See DR 225.
See DR 237. The resolution could then also read "Linear in last -
first".
</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<hr>
<a name="493"><h3>493.&nbsp;Undefined Expression in Input Iterator Note Title</h3></a><p><b>Section:</b>&nbsp;24.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.input.iterators"> [lib.input.iterators]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Chris Jefferson&nbsp; <b>Date:</b>&nbsp;13 Dec 2004</p>
<p>1) In 24.1.1/3, the following text is currently present.</p>
<p>"Note: For input iterators, a==b does not imply ++a=++b (Equality does
not guarantee the substitution property or referential transparency)."</p>
<p>However, when in Table 72, part of the definition of ++r is given as:</p>
<p>"pre: r is dereferenceable.
post: any copies of the previous value of r are no longer required
either to be dereferenceable ..."</p>
<p>While a==b does not imply that b is a copy of a, this statement should
perhaps still be made more clear.</p>
<p>2) There are no changes to intended behaviour</p>
<p>
3) This Note should be altered to say "Note: For input iterators a==b,
when its behaviour is defined ++a==++b may still be false (Equality does
not guarantee the substitution property or referential transparency).</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<hr>
<a name="494"><h3>494.&nbsp;Wrong runtime complexity for associative container's insert and delete</h3></a><p><b>Section:</b>&nbsp;23.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Hans B os&nbsp; <b>Date:</b>&nbsp;19 Dec 2004</p>
<p>According to [lib.associative.reqmts] table 69, the runtime comlexity
of insert(p, t) and erase(q) can be done in amortized constant time.</p>
<p>It was my understanding that an associative container could be
implemented as a balanced binary tree.</p>
<p>For inser(p, t), you 'll have to iterate to p's next node to see if t
can be placed next to p. Furthermore, the insertion usually takes
place at leaf nodes. An insert next to the root node will be done at
the left of the root next node</p>
<p>So when p is the root node you 'll have to iterate from the root to
its next node, which takes O(log(size)) time in a balanced tree.</p>
<p>If you insert all values with insert(root, t) (where root is the
root of the tree before insertion) then each insert takes O(log(size))
time. The amortized complexity per insertion will be O(log(size))
also.</p>
<p>For erase(q), the normal algorithm for deleting a node that has no
empty left or right subtree, is to iterate to the next (or previous),
which is a leaf node. Then exchange the node with the next and delete
the leaf node. Furthermore according to DR 130, erase should return
the next node of the node erased. Thus erasing the root node,
requires iterating to the next node.</p>
<p>Now if you empty a map by deleting the root node until the map is
empty, each operation will take O(log(size)), and the amortized
complexity is still O(log(size)).</p>
<p>The operations can be done in amortized constant time if iterating
to the next node can be done in (non amortized) constant time. This
can be done by putting all nodes in a double linked list. This
requires two extra links per node. To me this is a bit overkill since
you can already efficiently insert or erase ranges with erase(first,
last) and insert(first, last).</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<hr>
<a name="495"><h3>495.&nbsp;Clause 22 template parameter requirements</h3></a><p><b>Section:</b>&nbsp;22 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.localization"> [lib.localization]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;Beman Dawes&nbsp; <b>Date:</b>&nbsp;10 Jan 2005</p>
<p>It appears that there are no requirements specified for many of the
template parameters in clause 22. It looks like this issue has never
come up, except perhaps for Facet.</p>
<p>Clause 22 isn't even listed in 17.3.2.1 [lib.type.descriptions],
either, which is the wording that allows requirements on template
parameters to be identified by name.</p>
<p>So one issue is that 17.3.2.1 [lib.type.descriptions] Should be
changed to cover clause 22. A better change, which will cover us in
the future, would be to say that it applies to all the library
clauses. Then if a template gets added to any library clause we are
covered.</p>
<p>charT, InputIterator, and other names with requirements defined
elsewhere are fine, assuming the 17.3.2.1 [lib.type.descriptions] fix.
But there are a few template arguments names which I don't think have
requirements given elsewhere:</p>
<ul>
<li>internT and externT. The fix is to add wording saying that internT
and externT must meet the same requirements as template arguments
named charT.</li>
<li>stateT. I'm not sure about this one. There already is some wording,
but it seems a bit vague.</li>
<li>Intl. [lib.locale.moneypunct.byname] The fix for this one is to
rename "Intl" to "International". The name is important because other
text identifies the requirements for the name International but not
for Intl.</li>
</ul>
<p><b>Proposed resolution:</b></p>
<hr>
<a name="496"><h3>496.&nbsp;Illegal use of "T" in vector&lt;bool&gt;</h3></a><p><b>Section:</b>&nbsp;23.2.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.bool"> [lib.vector.bool]</a>&nbsp; <b>Status:</b>&nbsp;<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a>&nbsp; <b>Submitter:</b>&nbsp;richard@ex-parrot.com&nbsp; <b>Date:</b>&nbsp;10 Feb 2005</p>
<p>
In the synopsis of the std::vector&lt;bool&gt; specialisation in 23.2.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.bool"> [lib.vector.bool]</a>,
the non-template assign() function has the signature</p>
<pre> void assign( size_type n, const T&amp; t );
</pre>
<p>
The type, T, is not defined in this context and should be replaced by
bool or value_type.</p>
<p><b>Proposed resolution:</b></p>
<p>
</p>
<p>----- End of document -----</p>
</body></html>