| <!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 <austern@google.com></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. Num_get overflow result</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Nathan Myers <b>Date:</b> 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<T>::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. Vector<bool> is not a container</h3></a><p><b>Section:</b> 23.2.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.bool"> [lib.vector.bool]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> AFNOR <b>Date:</b> 7 Oct 1998</p> |
| <p><tt>vector<bool></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<bool> 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> |
| * Not A Defect.<br> |
| * Add a note explaining that vector<bool> does not meet |
| Container requirements.<br> |
| * Remove vector<bool>.<br> |
| * Add a new category of container requirements which |
| vector<bool> would meet.<br> |
| * Rename vector<bool>.<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<bool> in the next standard. (2) |
| Remove vector<bool> in the following standard.]</i></p> |
| |
| <p><i>[Modifying container requirements to permit returning proxies |
| (thus allowing container requirements conforming vector<bool>) |
| was also discussed.]</i></p> |
| |
| <p><i>[It was also noted that there is a partial but ugly workaround in |
| that vector<bool> may be further specialized with a customer |
| allocator.]</i></p> |
| |
| <p><i>[Kona: Herb Sutter presented his paper J16/99-0035==WG21/N1211, |
| vector<bool>: 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<bool> and introduce std::bit_vector. Then |
| gradually, over a period of years, we could reintroduce |
| std::vector<bool> but this time as an ordinary vector. (2) Change |
| iterarator and container requirements so that vector<bool> will |
| be a fully conforming container. These options are not mutually |
| exclusive.]</i></p> |
| <hr> |
| <a name="130"><h3>130. Return type of container::erase(iterator) differs for associative containers</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Andrew Koenig <b>Date:</b> 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. max_size() underspecified</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Andy Sawyer <b>Date:</b> 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> |
| the largest value that can meaningfully be |
| passed to X::allocate<br> |
| to:<br> |
| 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> |
| size() of the largest possible container.<br> |
| to:<br> |
| 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. Numeric limits terminology wrong</h3></a><p><b>Section:</b> 18.2.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-support.html#lib.limits"> [lib.limits]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Stephen Cleary <b>Date:</b> 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 <limits>, <climits>, and <cfloat> |
| supply characteristics of implementation-dependent fundamental types |
| (3.9.1).</p> |
| </blockquote> |
| |
| <p>to:</p> |
| <blockquote> |
| |
| <p> The headers <limits>, <climits>, and <cfloat> |
| 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. Insertion hints in associative containers</h3></a><p><b>Section:</b> 23.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Andrew Koenig <b>Date:</b> 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. <tt>vector</tt>, <tt>deque::insert</tt> complexity</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Lisa Lippincott <b>Date:</b> 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. Exception types in clause 19 are constructed from <tt>std::string</tt> |
| </h3></a><p><b>Section:</b> 19.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-diagnostics.html#lib.std.exceptions"> [lib.std.exceptions]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 01 Aug 2000</p> |
| <p> |
| Many of the standard exception types which implementations are |
| required to throw are constructed with a const std::string& |
| 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& 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& 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> 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& constructor, and the copy constructor. If a user writes |
| something like <tt>throw std::out_of_range("foo")</tt>, the const |
| string& 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& 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& 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. Missing allocator requirement</h3></a><p><b>Section:</b> 20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 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<U>::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. Comparison of reverse_iterator to const reverse_iterator</h3></a><p><b>Section:</b> 24.4.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.reverse.iterators"> [lib.reverse.iterators]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Steve Cleary <b>Date:</b> 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 < class U > |
| reverse_iterator < Iterator >& operator=(const reverse_iterator< U >& u); |
| |
| B) Make all global functions (except the operator+) have |
| two template parameters instead of one, that is, for |
| operator ==, !=, <, >, <=, >=, - replace: |
| |
| template < class Iterator > |
| typename reverse_iterator< Iterator >::difference_type operator-( |
| const reverse_iterator< Iterator >& x, |
| const reverse_iterator< Iterator >& y); |
| |
| with: |
| |
| template < class Iterator1, class Iterator2 > |
| typename reverse_iterator < Iterator1 >::difference_type operator-( |
| const reverse_iterator < Iterator1 > & x, |
| const reverse_iterator < Iterator2 > & 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. Requirements to for_each and its function object</h3></a><p><b>Section:</b> 25.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.foreach"> [lib.alg.foreach]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Angelika Langer <b>Date:</b> 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. User defined macros and standard headers</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> James Kanze <b>Date:</b> 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 <sstream> |
| </pre> |
| |
| <p>since npos is not defined in <sstream>. It is, however, defined |
| in <string>, and it is hard to imagine an implementation in |
| which <sstream> didn't include <string>.</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. Incorrect return types for iterator dereference</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> John Potter <b>Date:</b> 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&. *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& 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&</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&</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. Does sentry catch exceptions?</h3></a><p><b>Section:</b> 27.6 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.iostream.format"> [lib.iostream.format]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 19 Mar 2001</p> |
| <p> |
| The descriptions of the constructors of basic_istream<>::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<>::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<>::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<>::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()->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& operator>> (istream &strm, S &s) |
| { |
| ios::iostate err = ios::goodbit; |
| try { |
| const istream::sentry guard (strm, false); |
| if (guard) { |
| use_facet<num_get<char> >(strm.getloc ()) |
| .get (istreambuf_iterator<char>(strm), |
| istreambuf_iterator<char>(), |
| 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& operator>> (istream &strm, S &s) |
| { |
| istream::sentry guard (strm, false); |
| if (guard) { |
| ios::iostate err = ios::goodbit; |
| try { |
| use_facet<num_get<char> >(strm.getloc ()) |
| .get (istreambuf_iterator<char>(strm), |
| istreambuf_iterator<char>(), |
| 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& operator>> (istream &strm, S &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<num_get<char> >(strm.getloc ()) |
| .get (istreambuf_iterator<char>(strm), |
| istreambuf_iterator<char>(), |
| strm, err, s.i); |
| } |
| } |
| catch (...) { |
| if (thrown && state & 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. seek and eofbit</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Howard Hinnant <b>Date:</b> 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()>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()&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. Meaning of ctype_base::mask enumerators</h3></a><p><b>Section:</b> 22.2.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.category.ctype"> [lib.category.ctype]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 23 Jan 2002</p> |
| |
| <p>What should the following program print?</p> |
| |
| <pre> #include <locale> |
| #include <iostream> |
| |
| class my_ctype : public std::ctype<char> |
| { |
| typedef std::ctype<char> 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 << "isspace: " << ct.is(std::ctype_base::space, '_') << " " |
| << "isalpha: " << ct.is(std::ctype_base::alpha, '_') << 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<char>, 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 -> !isalpha. |
| -------- |
| |
| #include <locale> |
| #include <iostream> |
| |
| class my_ctype : public std::ctype<char> |
| { |
| private: |
| typedef std::ctype<char> 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<mask>('_')] = both; |
| } |
| }; |
| |
| int main() |
| { |
| using namespace std; |
| my_ctype ct; |
| cout << "isspace: " << ct.is(ctype_base::space, '_') << endl; |
| cout << "isprint: " << ct.is(ctype_base::print, '_') << endl; |
| |
| // ISO C99, isalpha iff upper | lower set, and !space. |
| // 7.5, p 193 |
| // -> looks like g++ behavior is correct. |
| // 356 -> bitmask elements are required for ctype_base |
| // 339 -> bitmask type required for mask |
| cout << "isalpha: " << ct.is(ctype_base::alpha, '_') << 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. bind1st/bind2nd type safety</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Andrew Demkin <b>Date:</b> 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), &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<Operation>( op, |
| static_cast<typename Operation::first_argument_type>(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<T>(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. Excessive const-qualification</h3></a><p><b>Section:</b> 27 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.input.output"> [lib.input.output]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Walter Brown, Marc Paterno <b>Date:</b> 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<charT,traits>* tie() const; |
| </pre> |
| <p>with</p> |
| <pre> basic_ostream<charT,traits>* tie(); |
| const basic_ostream<charT,traits>* tie() const; |
| </pre> |
| |
| <p>and replace</p> |
| <pre> basic_streambuf<charT,traits>* rdbuf() const; |
| </pre> |
| <p>with</p> |
| <pre> basic_streambuf<charT,traits>* rdbuf(); |
| const basic_streambuf<charT,traits>* 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<charT,traits,Allocator>* rdbuf() const; |
| </pre> |
| <p>with</p> |
| <pre> basic_stringbuf<charT,traits,Allocator>* rdbuf(); |
| const basic_stringbuf<charT,traits,Allocator>* 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<charT,traits>* rdbuf() const; |
| </pre> |
| <p>with</p> |
| <pre> basic_filebuf<charT,traits>* rdbuf(); |
| const basic_filebuf<charT,traits>* rdbuf() const; |
| </pre> |
| <hr> |
| <a name="368"><h3>368. basic_string::replace has two "Throws" paragraphs</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Beman Dawes <b>Date:</b> 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. io stream objects and static ctors</h3></a><p><b>Section:</b> 27.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.iostream.objects"> [lib.iostream.objects]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Ruslan Abdikeev <b>Date:</b> 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<charT,traits>::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 <iostream> 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 <iostream>. |
| </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) |
| <iostream> 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 <iostream> 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 <iostream>. 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 <iostream> 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 |
| <iostream> 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 << "foo()\n").rdstate (); } |
| int i = foo (); |
| int main () { return i; } |
| </pre> |
| <hr> |
| <a name="371"><h3>371. Stability of multiset and multimap member functions</h3></a><p><b>Section:</b> 23.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Frank Compagner <b>Date:</b> 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<int, int> m; |
| multimap<int, int>::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. basic_streambuf semantics</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Ray Lischner <b>Date:</b> 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 & (ios_base::in|ios_base::out)) == ios_base::in |
| </p> |
| |
| <p> |
| (which & (ios_base::in|ios_base::out)) == ios_base::out |
| </p> |
| |
| <p> |
| (which & (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 & 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. codecvt do_in/out result</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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->N conversion in mind, not M->N. |
| Bill, Howard, and Martin will provide new wording. |
| ]</i></p> |
| <hr> |
| <a name="384"><h3>384. equal_range has unimplementable runtime complexity</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Hans Bos <b>Date:</b> 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(&x, &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. Does call by value imply the CopyConstructible requirement?</h3></a><p><b>Section:</b> 17 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.library"> [lib.library]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 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<my_iterator, |
| my_predicate&></tt>. The question is whether implementation |
| are required to accept this, or whether this is ill-formed because |
| my_predicate& 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. Reverse iterator's operator[] has impossible return type</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 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<>::operator[]</tt> |
| is specified as having a return type of <tt>reverse_iterator::reference</tt>, |
| which is the same as <tt>iterator_traits<Iterator>::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<Iterator>::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. std::complex over-encapsulated</h3></a><p><b>Section:</b> 26.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-numerics.html#lib.complex.numbers"> [lib.complex.numbers]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Gabriel Dos Reis <b>Date:</b> 8 Nov 2002</p> |
| <p> |
| The absence of explicit description of std::complex<T> 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<T> whenever T |
| is a numerical datatype. The absence of ways to access individual |
| parts of a std::complex<T> 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<T> z; |
| // ... |
| // set the real part to r |
| z = complex<T>(r, z.imag()); |
| // ... |
| // set the imaginary part to i |
| z = complex<T>(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<> 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<T> then</p> |
| |
| <ul> |
| <li>the expression reinterpret_cast<cv T(&)[2]>(z) |
| is well-formed; and</li> |
| <li>reinterpret_cast<cvT(&)[2]>(z)[0]designates the |
| real part of z; and</li> |
| <li>reinterpret_cast<cvT(&)[2]>(z)[1]designates the |
| imaginary part of z.</li> |
| </ul> |
| |
| <p> |
| Moreover, if a is an expression of pointer type cv complex<T>* |
| and the expression a[i] is well-defined for an integer expression |
| i then: |
| </p> |
| |
| <ul> |
| <li>reinterpret_cast<cvT*>(a)[2+i] designates the real |
| part of a[i]; and</li> |
| <li>reinterpret_cast<cv T*>(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<class T> T real(const complex<T>&); |
| template<class T> T imag(const complex<T>&); |
| </pre> |
| |
| <p>with</p> |
| |
| <pre> template<class T> const T& real(const complex<T>&); |
| template<class T> T& real( complex<T>&); |
| template<class T> const T& imag(const complex<T>&); |
| template<class T> T& imag( complex<T>&); |
| </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<class T> T real(const complex<T>&); |
| </pre> |
| <p>to</p> |
| <pre> template<class T> const T& real(const complex<T>&); |
| template<class T> T& real( complex<T>&); |
| </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<class T> T imag(const complex<T>&); |
| </pre> |
| <p>to</p> |
| <pre> template<class T> const T& imag(const complex<T>&); |
| template<class T> T& imag( complex<T>&); |
| </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. behavior of formatted output on failure</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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<num_put<charT,ostreambuf_iterator<charT,traits> |
| > > |
| (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<<(int) will |
| set badbit if the disk is full, while operator<<(ostream&, |
| 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. what are characters zero and one</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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 <class charT, class traits, class Allocator> |
| explicit |
| bitset(const basic_string<charT, traits, Allocator>& str, |
| typename basic_string<charT, traits, Allocator>::size_type pos = 0, |
| typename basic_string<charT, traits, Allocator>::size_type n = |
| basic_string<charT, traits, Allocator>::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 <class charT, class traits, class Allocator> |
| basic_string<charT, traits, Allocator> |
| 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 << x.template to_string<charT,traits,allocator<charT> >( |
| use_facet<ctype<charT> >(<i>os</i>.getloc()).widen('0'), |
| use_facet<ctype<charT> >(<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. ostream::sentry dtor throws exceptions</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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() & ios_base::unitbuf) && !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()->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. effects of end-of-file on unformatted input functions</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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<charT, traits>& |
| 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<charT, traits>& |
| get (char_type*, streamsize); |
| </pre> |
| <p></p> |
| <p> |
| Also sets failbit if it fails to extract any characters. |
| </p> |
| <p> |
| </p><pre> basic_istream<charT, traits>& |
| 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<charT, traits>& |
| getline (char_type*, streamsize); |
| </pre> |
| <p></p> |
| <p> |
| Also sets failbit if it fails to extract any characters. |
| </p> |
| <p> |
| </p><pre> basic_istream<charT, traits>& |
| ignore (int, int_type); |
| </pre> |
| <p></p> |
| <p> |
| </p><pre> basic_istream<charT, traits>& |
| 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<charT, traits>& |
| get (char_type&); |
| </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<charT, traits>& |
| get (basic_streambuf<charT, traits>&, char_type); |
| </pre> |
| <p></p> |
| <p> |
| </p><pre> basic_istream<charT, traits>& |
| get (basic_streambuf<charT, traits>&); |
| </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. incorrect type casts in table 32 in lib.allocator.requirements</h3></a><p><b>Section:</b> 20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Markus Mauhart <b>Date:</b> 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)?->~T() |
| </pre> |
| |
| <p> |
| .... with the prerequisits coming from the preceding two paragraphs, especially |
| from table 31: |
| </p> |
| |
| <pre> alloc<T> a ;// an allocator for T |
| alloc<T>::pointer p ;// random access iterator |
| // (may be different from T*) |
| alloc<T>::reference r = *p;// T& |
| T const& 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<T>::pointer, so it would implicitely introduce extra |
| requirements for alloc<T>::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*)&*p" and that |
| "((T*)p)?->" should be replaced with "(*p)." or with |
| "(&*p)->". |
| </p> |
| |
| <p> |
| Note: Actually I would prefer to replace "((T*)p)?->dtor_name" with |
| "p?->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. vector::insert(s) exception safety</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 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. Is vector<reverse_iterator<char*> > forbidden?</h3></a><p><b>Section:</b> 24.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Nathan Myers <b>Date:</b> 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<> in the default |
| constructor. As a result, code like |
| </p> |
| <blockquote> |
| std::vector<std::reverse_iterator<char*> > 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<std::reverse_iterator<char*> > 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<T> 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 <typename Iterator> |
| void f() { std::vector<Iterator> v(7); } |
| </blockquote> |
| <p> |
| evoke undefined behavior for some conforming iterator definitions? |
| I think it does, now, because vector<> 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. Closing an fstream should clear error state</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Nathan Myers <b>Date:</b> 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()->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()->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()->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()->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()->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()->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. Proposed resolution to LDR#64 still wrong</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Bo Persson <b>Date:</b> 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. definitions of XXX_MIN and XXX_MAX macros in climits</h3></a><p><b>Section:</b> 18.2.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-support.html#lib.c.limits"> [lib.c.limits]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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 <climits> and <limits.h> |
| 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) > 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 <limits> instead of |
| <climits>.]</i></p> |
| |
| <hr> |
| <a name="417"><h3>417. what does ctype::do_widen() return on failure</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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<wchar_t> 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. exceptions thrown during iostream cleanup</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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. istream extractors not setting failbit if eofbit is already set</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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 <sstream> |
| #include <cstdio> |
| |
| int main() |
| { |
| std::istringstream strm ("1"); |
| |
| int i = 0; |
| |
| strm >> i; |
| |
| std::printf ("eof = %d, fail = %d\n", |
| !!strm.eof (), !!strm.fail ()); |
| |
| strm >> 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 >> 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. is basic_streambuf copy-constructible?</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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& sb); |
| basic_streambuf& operator=(const basic_streambuf& sb); |
| </pre> |
| </blockquote> |
| |
| <p>Insert after 27.5.2.1, paragraph 2:</p> |
| <blockquote> |
| <pre>basic_streambuf(const basic_streambuf& 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& operator=(const basic_streambuf& 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&); // not defined |
| basic_stringbuf& operator=(const basic_stringbuf&); // 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& sb); |
| basic_stringbuf& operator=(const basic_stringbuf& sb); |
| </pre> |
| |
| <p>27.7.1.1, insert after paragraph 4:</p> |
| |
| <pre>basic_stringbuf(const basic_stringbuf& 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& operator=(const basic_stringbuf& 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&); // not defined |
| basic_filebuf& operator=(const basic_filebuf&); // 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. explicit specializations of member functions of class templates</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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. effects of negative streamsize in iostreams</h3></a><p><b>Section:</b> 27 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.input.output"> [lib.input.output]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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 >= 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 >= 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. normative notes</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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. stage 2 and rationale of DR 221</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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<charT>:: |
| 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<charT> 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<charT></tt></p>. |
| |
| <hr> |
| <a name="430"><h3>430. valarray subset operations</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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. Swapping containers with unequal allocators</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 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<int, my_alloc></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<int, my_alloc> v1(a1); |
| vector<int, my_alloc> 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. bitset::to_string() hard to use</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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 <class charT, class traits> |
| basic_string<charT, traits, allocator<charT> > |
| to_string () const; |
| |
| -34.1- Returns: to_string<charT, traits, allocator<charT> >(). |
| |
| template <class charT> |
| basic_string<charT, char_traits<charT>, allocator<charT> > |
| to_string () const; |
| |
| -34.2- Returns: to_string<charT, char_traits<charT>, allocator<charT> >(). |
| |
| basic_string<char, char_traits<char>, allocator<char> > |
| to_string () const; |
| |
| -34.3- Returns: to_string<char, char_traits<char>, allocator<char> >(). |
| </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. Ambiguity in the "do the right thing" clause</h3></a><p><b>Section:</b> 23.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.sequence.reqmts"> [lib.sequence.reqmts]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Howard Hinnant <b>Date:</b> 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<int> v(10, 1); |
| </pre> |
| |
| <p>The intent of the above statement was to construct with:</p> |
| <pre>vector(size_type, const value_type&); |
| </pre> |
| |
| <p>but early implementations failed to compile as they bound to:</p> |
| <pre>template <class InputIterator> |
| 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<static_cast<size_type>(f), static_cast<value_type>(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 <class T> |
| struct vector |
| { |
| typedef unsigned size_type; |
| |
| explicit vector(size_type) {} |
| vector(size_type, const T&) {} |
| |
| template <class I> |
| vector(I, I); |
| |
| // ... |
| }; |
| |
| template <class T> |
| template <class I> |
| vector<T>::vector(I, I) { ... } |
| |
| template <> |
| template <> |
| vector<int>::vector(int, int) { ... } |
| |
| template <> |
| template <> |
| vector<int>::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 <class T> |
| template <class I> |
| vector<T>::vector(I f, I l) |
| { |
| choose_init(f, l, int2type<is_integral<I>::value>()); |
| } |
| |
| template <class T> |
| template <class I> |
| vector<T>::choose_init(I f, I l, int2type<false>) |
| { |
| // construct with iterators |
| } |
| |
| template <class T> |
| template <class I> |
| vector<T>::choose_init(I f, I l, int2type<true>) |
| { |
| size_type sz = static_cast<size_type>(f); |
| value_type v = static_cast<value_type>(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<int> 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<char, char> p('a', 'b'); |
| vector<vector<pair<char, char> > > 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 <> |
| template <> |
| vector<vector<pair<char, char> > >::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<size_type>('a') by |
| static_cast<size_type>('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<vector<pair<char, char> > > 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 <class T, class U> |
| inline |
| T implicit_cast(const U& 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 <class InputIterator> |
| X(InputIterator f, InputIterator l, |
| const allocator_type& 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& = value_type(), |
| const allocator_type& = allocator_type()) |
| </pre> |
| <p>were called instead, with the arguments static_cast<size_type>(f), l and a, respectively.</p> |
| </li> |
| |
| <li> |
| <p>If the member functions of the forms:</p> |
| <pre> template <class InputIterator> // such as insert() |
| rt fx1(iterator p, InputIterator f, InputIterator l); |
| |
| template <class InputIterator> // such as append(), assign() |
| rt fx2(InputIterator f, InputIterator l); |
| |
| template <class InputIterator> // 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&); |
| |
| rt fx2(size_type, const value_type&); |
| |
| rt fx3(iterator, iterator, size_type, const value_type&); |
| </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<vector<int> >(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<int> 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<vector<T> > v(10, 1); |
| </pre> |
| |
| <p> |
| because the integral type 1 is not *implicitly* convertible to |
| vector<T>. 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<B> 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. Bad use of casts in fstream</h3></a><p><b>Section:</b> 27.8.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.fstreams"> [lib.fstreams]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Vincent Leloup <b>Date:</b> 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<charT,traits>*)&sb. |
| </blockquote> |
| |
| <p>to:</p> |
| <blockquote> |
| Returns: const_cast<basic_filebuf<charT,traits>*>(&sb). |
| </blockquote> |
| |
| <p>Change 27.8.1.10/1 from:</p> |
| <blockquote> |
| Returns: (basic_filebuf<charT,traits>*)&sb. |
| </blockquote> |
| |
| <p>to:</p> |
| <blockquote> |
| Returns: const_cast<basic_filebuf<charT,traits>*>(&sb). |
| </blockquote> |
| |
| <p>Change 27.8.1.13/1 from:</p> |
| <blockquote> |
| Returns: &sb. |
| </blockquote> |
| |
| <p>to:</p> |
| <blockquote> |
| Returns: const_cast<basic_filebuf<charT,traits>*>(&sb). |
| </blockquote> |
| |
| |
| |
| <hr> |
| <a name="445"><h3>445. iterator_traits::reference unspecified for some iterator categories</h3></a><p><b>Section:</b> 24.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.iterator.traits"> [lib.iterator.traits]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 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& 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& 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<V>(static_cast<R>(*a)) is equivalent to |
| static_cast<V>(*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<bool>'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-></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&</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<Iterator>::reference |
| iterator_traits<Iterator>::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-></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<Iterator>::difference_type |
| iterator_traits<Iterator>::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<Iterator>::difference_type |
| iterator_traits<Iterator>::value_type |
| iterator_traits<Iterator>::reference |
| iterator_traits<Iterator>::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&> |
| </pre> |
| </blockquote> |
| <p>to:</p> |
| <blockquote> |
| <pre>typename traits::off_type, charT*, charT> |
| </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. Iterator equality between different containers</a></h3><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Andy Koenig <b>Date:</b> 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. basic_stringbuf::seekoff need not always fail for an empty stream</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Bill Plauger <b>Date:</b> 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. basic_filebuf::open should accept wchar_t names</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Bill Plauger <b>Date:</b> 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<charT,traits>* 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<charT,traits>* open( |
| const char* s, |
| ios_base::openmode mode ); |
| |
| basic_filebuf<charT,traits>* 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. cerr::tie() and wcerr::tie() are overspecified</h3></a><p><b>Section:</b> 27.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.iostream.objects"> [lib.iostream.objects]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Bill Plauger <b>Date:</b> 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 &cout. |
| Its state is otherwise the same as required for basic_ios<char>::init |
| (lib.basic.ios.cons). |
| </blockquote> |
| |
| <p>Add to the description of wcerr:</p> |
| |
| <blockquote> |
| After the object wcerr is initialized, wcerr.tie() returns &wcout. |
| Its state is otherwise the same as required for basic_ios<wchar_t>::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. Traditional C header files are overspecified</h3></a><p><b>Section:</b> 17.4.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.headers"> [lib.headers]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Bill Plauger <b>Date:</b> 30 Jan 2004</p> |
| |
| <p>The C++ Standard effectively requires that the traditional C headers |
| (of the form <xxx.h>) be defined in terms of the newer C++ |
| headers (of the form <cxxx>). Clauses 17.4.1.2/4 and D.5 combine |
| to require that:</p> |
| |
| <ul> |
| <li>Including the header <cxxx> declares a C name in namespace std.</li> |
| |
| <li> Including the header <xxx.h> declares a C name in namespace std |
| (effectively by including <cxxx>), 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 <xxx.h> declares a C name in the |
| global namespace.</li> |
| |
| <li> Including the header <cxxx> declares a C name in the |
| global namespace (effectively by including <xxx.h>), 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 <xxx.h>. 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 <cxxx.h>. 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 <string> 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. bitset constructor: incorrect number of initialized bits</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Dag Henriksson <b>Date:</b> 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. 24.1.5 contains unintented limitation for operator-</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Daniel Frey <b>Date:</b> 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 >= 0) |
| while (m--) --r; |
| else |
| while (m++) ++r; |
| return r; } |
| </code> |
| |
| <hr> |
| <a name="459"><h3>459. Requirement for widening in stage 2 is overspecification</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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<wchar_t>::narrow (wchar_t wc, char dflt) const |
| { |
| const unsigned wi = unsigned (wc); |
| |
| if (wi > UCHAR_MAX) |
| return typeid (*this) == typeid (ctype<wchar_t>) ? |
| dflt : do_narrow (wc, dflt); |
| |
| if (narrow_ [wi] < 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<charT>::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<charT>::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. Default modes missing from basic_fstream member specifications</h3></a><p><b>Section:</b> 27.8.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iostreams.html#lib.fstreams"> [lib.fstreams]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Ben Hutchings <b>Date:</b> 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. time_get hard or impossible to implement</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a> <b>Submitter:</b> Bill Plauger <b>Date:</b> 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& str, |
| ios_base::iostate& 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<>::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& str, |
| ios_base::iostate& 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<>::put to produce the format specified by 'x', or until it |
| encounters an error. |
| </p> |
| |
| <p> |
| <b>change:</b> used by time_put<>::put to produce the format |
| specified by 'x', or until it encounters an error. |
| </p> |
| |
| <p><b>to:</b> used by time_put<>:: 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. Destroying objects with static storage duration</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Bill Plauger <b>Date:</b> 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. auto_ptr usability issues</h3></a><p><b>Section:</b> 20.4.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.auto.ptr"> [lib.auto.ptr]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Rani Sharoni <b>Date:</b> 7 Dec 2003</p> |
| |
| <p> |
| TC1 CWG DR #84 effectively made the template<class Y> operator auto_ptr<Y>() |
| 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 <memory> |
| using std::auto_ptr; |
| |
| struct B {}; |
| struct D : B {}; |
| |
| auto_ptr<D> source(); |
| int sink(auto_ptr<B>); |
| 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<D> 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<class Y> auto_ptr(auto_ptr<Y>& 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<B>()); |
| </pre> |
| |
| <p> |
| IMHO no one ever wrote such awkward code and the reasonable workaround for |
| #1 is: |
| </p> |
| <pre>int y = sink( auto_ptr<B>(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<B>, std::string); |
| auto_ptr<B> 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<B>::operator auto_ptr_ref<B>()</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<Y> that holds *this and this is another defect since |
| the type of *this is auto_ptr<X> where X might be different from Y. Several |
| library vendors (e.g. SGI) implement auto_ptr_ref<Y> 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<B>(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<class Y> auto_ptr(auto_ptr<Y> const&) |
| 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<class X> 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&) throw(); |
| template<class Y> auto_ptr(auto_ptr<Y> const&) throw(); |
| auto_ptr& operator=(auto_ptr&) throw(); |
| template<class Y> auto_ptr& operator=(auto_ptr<Y>) throw(); |
| ~auto_ptr() throw(); |
| |
| // 20.4.5.2 members: |
| X& operator*() const throw(); |
| X* operator->() const throw(); |
| X* get() const throw(); |
| X* release() throw(); |
| void reset(X* p=0) throw(); |
| |
| private: |
| template<class U> |
| auto_ptr(U& rhs, typename |
| unspecified_error_on_const_auto_ptr<U>::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<typename T> struct unspecified_error_on_const_auto_ptr; |
| |
| template<typename T> |
| struct unspecified_error_on_const_auto_ptr<auto_ptr<T> const> |
| { typedef typename auto_ptr<T>::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<X> from const auto_ptr<Y> 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<class Y> auto_ptr(auto_ptr<Y> const& a) throw();</pre> |
| <p> 4 Requires: Y* can be implicitly converted to X*.</p> |
| <p> 5 Effects: Calls const_cast<auto_ptr<Y>&>(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<class Y> auto_ptr& operator=(auto_ptr<Y> 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& 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&) |
| // implicit X& operator=(X&) |
| auto_ptr<D> 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<Y> 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<X> 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<Y> is |
| constructed from auto_ptr<X> 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. Suggestion for new member functions in standard containers</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a> <b>Submitter:</b> Thorsten Ottosen <b>Date:</b> 12 May 2004</p> |
| |
| <p>To add slightly more convenience to vector<T> and map<Key,T> we should consider to add</p> |
| <ol> |
| <li> add vector<T>::data() member (const and non-const version) |
| semantics: if( empty() ) return 0; else return buffer_;</li> |
| <li> add map<Key,T>::at( const Key& 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<T,sz> 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& at(const key_type& x); |
| const T& at(const key_type& 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& at(const key_type& x); |
| const T& at(const key_type& 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. Contents of <ciso646></h3></a><p><b>Section:</b> 17.4.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-intro.html#lib.headers"> [lib.headers]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a> <b>Submitter:</b> Steve Clamage <b>Date:</b> 3 Jun 2004</p> |
| <p>C header <iso646.h> 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 <cname> C++ header contents are the same |
| as the C header <name.h>. In particular, table 12 lists |
| <ciso646> as a C++ header.</p> |
| |
| <p>I don't find any other mention of <ciso646>, or any mention of |
| <iso646.h>, in clauses 17 thorough 27. That implies that the |
| contents of <ciso646> are the same as C header <iso646.h>.</p> |
| |
| <p>Annex C (informative, not normative) in [diff.header.iso646.h] C.2.2.2 |
| "Header <iso646.h>" says that the alternative tokens are not |
| defined as macros in <ciso646>, but does not mention the contents |
| of <iso646.h>.</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 <iso646.h> |
| or <ciso646> has no effect. </p> |
| </blockquote> |
| |
| <p><i>[post-Redmond: Steve provided wording.]</i></p> |
| |
| <hr> |
| <a name="466"><h3>466. basic_string ctor should prevent null pointer error</h3></a><p><b>Section:</b> 21.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-strings.html#lib.string.cons"> [lib.string.cons]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Daniel Frey <b>Date:</b> 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 <string> |
| 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. char_traits::lt(), compare(), and memcmp()</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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<char>::lt() |
| to yield the same result as operator<(char, char). |
| </p> |
| |
| <p> |
| Most, if not all, implementations of char_traits<char>::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 < 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 < 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. unexpected consequences of ios_base::operator void*()</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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 <cassert> |
| #include <iostream> |
| |
| 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<charT, traits>::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. vector<bool> ill-formed relational operators</h3></a><p><b>Section:</b> 23.2.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.bool"> [lib.vector.bool]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 28 Jun 2004</p> |
| |
| <p> |
| The overloads of relational operators for vector<bool> 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<bool> from [lib.vector.bool]. |
| </p> |
| <hr> |
| <a name="470"><h3>470. accessing containers from their elements' special functions</h3></a><p><b>Section:</b> 23 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.containers"> [lib.containers]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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. result of what() implementation-defined</h3></a><p><b>Section:</b> 18.6.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-support.html#lib.exception"> [lib.exception]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 28 Jun 2004</p> |
| |
| <p>[lib.exception] specifies the following:</p> |
| <pre> exception (const exception&) throw(); |
| exception& operator= (const exception&) 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. Missing "Returns" clause in std::equal_range</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#Review">Review</a> <b>Submitter:</b> Prateek R Karandikar <b>Date:</b> 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. underspecified ctype calls</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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(&c, &c + 1, &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. confusing Footnote 297</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 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<char>), 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. May the function object passed to for_each modify the elements of the iterated sequence?</h3></a><p><b>Section:</b> 25.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.foreach"> [lib.alg.foreach]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Stephan T. Lavavej, Jaakko Jarvi <b>Date:</b> 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. Forward Iterator implied mutability</h3></a><p><b>Section:</b> 24.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 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. Operator-> for const forward iterators</h3></a><p><b>Section:</b> 24.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 11 Jul 2004</p> |
| <p> |
| The Forward Iterator requirements table contains the following: |
| </p> |
| <pre> expression return type operational precondition |
| semantics |
| ========== ================== =========== ========================== |
| a->m U& if X is mutable, (*a).m pre: (*a).m is well-defined. |
| otherwise const U& |
| |
| r->m U& (*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&, 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. Should forward iterator requirements table have a line for r->m?</h3></a><p><b>Section:</b> 24.1.3 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 11 Jul 2004</p> |
| <p> |
| The Forward Iterator requirements table contains the following: |
| </p> |
| <pre> expression return type operational precondition |
| semantics |
| ========== ================== =========== ========================== |
| a->m U& if X is mutable, (*a).m pre: (*a).m is well-defined. |
| otherwise const U& |
| |
| r->m U& (*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&, 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. Container requirements and placement new</h3></a><p><b>Section:</b> 23.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Herb Sutter <b>Date:</b> 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<C> 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. unary_function and binary_function should have protected nonvirtual destructors</h3></a><p><b>Section:</b> 20.3.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.base"> [lib.base]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Joe Gottman <b>Date:</b> 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<int, int, int> *p = new plus<int>; 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 <class Arg, class Result> |
| struct unary_function { |
| typedef Arg argument_type; |
| typedef Result result_type; |
| }; |
| |
| template <class Arg1, class Arg2, class Result> |
| struct binary_function { |
| typedef Arg1 first_argument_type; |
| typedef Arg2 second_argument_type; |
| typedef Result result_type; |
| }; |
| </pre> |
| |
| <p>to</p> |
| <pre> template <class Arg, class Result> |
| struct unary_function { |
| typedef Arg argument_type; |
| typedef Result result_type; |
| protected: |
| ~unary_function() {} |
| }; |
| |
| template <class Arg1, class Arg2, class Result> |
| 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. unique's effects on the range [result, last)</h3></a><p><b>Section:</b> 25.2.8 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.unique"> [lib.alg.unique]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Andrew Koenig <b>Date:</b> 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. Swapping pairs</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Andrew Koenig <b>Date:</b> 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<vector<int>, |
| list<double> > should not take O(1).</p> |
| <p><b>Proposed resolution:</b></p> |
| <hr> |
| <a name="484"><h3>484. Convertible to T</h3></a><p><b>Section:</b> 24.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.input.iterators"> [lib.input.iterators]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Chris <b>Date:</b> 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 && *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. output iterator insufficently constrained</h3></a><p><b>Section:</b> 24.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.output.iterators"> [lib.output.iterators]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Chris <b>Date:</b> 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. Allocator::construct is too limiting</h3></a><p><b>Section:</b> 20.1.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Dhruv Matani <b>Date:</b> 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<typename T> |
| struct allocator{ |
| template<typename T1> |
| void construct(pointer T1 const& 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. rotate throws away useful information</h3></a><p><b>Section:</b> 25.2.10 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.rotate"> [lib.alg.rotate]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Howard Hinnant <b>Date:</b> 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<class ForwardIterator> |
| void rotate(ForwardIterator first, ForwardIterator middle, |
| ForwardIterator last); |
| </pre> |
| |
| <p>to:</p> |
| |
| <pre> template<class ForwardIterator> |
| ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, |
| ForwardIterator last); |
| </pre> |
| |
| <p>In 25.2.10, change:</p> |
| |
| <pre> template<class ForwardIterator> |
| void rotate(ForwardIterator first, ForwardIterator middle, |
| ForwardIterator last); |
| </pre> |
| |
| <p>to:</p> |
| |
| <pre> template<class ForwardIterator> |
| 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. std::remove / std::remove_if wrongly specified</h3></a><p><b>Section:</b> 25.2.7 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.remove"> [lib.alg.remove]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Thomas Mang <b>Date:</b> 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. std::unique wrongly specified</h3></a><p><b>Section:</b> 25.2.8 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-algorithms.html#lib.alg.unique"> [lib.alg.unique]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Thomas Mang <b>Date:</b> 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. std::list<>::unique incorrectly specified</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Thomas Mang <b>Date:</b> 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<T, Allocator>::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. Invalid iterator arithmetic expressions</h3></a><p><b>Section:</b> 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> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Thomas Mang <b>Date:</b> 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. Undefined Expression in Input Iterator Note Title</h3></a><p><b>Section:</b> 24.1.1 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-iterators.html#lib.input.iterators"> [lib.input.iterators]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Chris Jefferson <b>Date:</b> 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. Wrong runtime complexity for associative container's insert and delete</h3></a><p><b>Section:</b> 23.1.2 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Hans B os <b>Date:</b> 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. Clause 22 template parameter requirements</h3></a><p><b>Section:</b> 22 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-locales.html#lib.localization"> [lib.localization]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> Beman Dawes <b>Date:</b> 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. Illegal use of "T" in vector<bool></h3></a><p><b>Section:</b> 23.2.5 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lib-containers.html#lib.vector.bool"> [lib.vector.bool]</a> <b>Status:</b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#New">New</a> <b>Submitter:</b> richard@ex-parrot.com <b>Date:</b> 10 Feb 2005</p> |
| <p> |
| In the synopsis of the std::vector<bool> 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& 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> |