
2004-07-29 Paolo Carlini <pcarlini@suse.de> * docs/html/ext/lwg-active.html, lwg-defects.html: Import Revision 31. From-SVN: r85310
6415 lines
269 KiB
HTML
6415 lines
269 KiB
HTML
<!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>
|
|
<tr>
|
|
<td align="left">Doc. no.</td>
|
|
<td align="left">N1657=04-0097</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="left">Date:</td>
|
|
<td align="left">16 Jul 2004</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@apple.com></td>
|
|
</tr>
|
|
</table>
|
|
<h1>C++ Standard Library Active Issues List (Revision 31)</h1>
|
|
<p>Reference ISO/IEC IS 14882:1998(E)</p>
|
|
<p>Also see:</p>
|
|
<ul>
|
|
<li>
|
|
<a href="lwg-toc.html">Table of Contents</a> for all library issues.</li>
|
|
<li>
|
|
<a href="lwg-index.html">Index by Section</a> for all library issues.</li>
|
|
<li>
|
|
<a href="lwg-status.html">Index by Status</a> for all library issues.</li>
|
|
<li><a href="lwg-defects.html">Library Defect Reports List</a></li>
|
|
<li><a href="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 or other extensions. </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="lwg-active.html#New">New</a>, <a href="lwg-active.html#Open">Open</a>,
|
|
<a href="lwg-active.html#Ready">Ready</a>, and <a href="lwg-active.html#Review">Review</a>. See
|
|
<a href="lwg-defects.html">Library Defect Reports List</a> for issues considered defects and
|
|
<a href="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.dkuug.dk/jtc1/sc22/wg21">http://www.dkuug.dk/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>R31:
|
|
2004-07 mid-term mailing: reflects new proposed resolutions and
|
|
new issues received after the post-Sydney mailing. Added
|
|
new issues <a href="lwg-active.html#463">463</a>-<a href="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="lwg-active.html#460">460</a>-<a href="lwg-active.html#462">462</a>.
|
|
</li>
|
|
<li>R29:
|
|
Pre-Sydney mailing. Added new issues <a href="lwg-active.html#441">441</a>-<a href="lwg-active.html#457">457</a>.
|
|
</li>
|
|
<li>R28:
|
|
Post-Kona mailing: reflects decisions made at the Kona meeting.
|
|
Added new issues <a href="lwg-active.html#432">432</a>-<a href="lwg-closed.html#440">440</a>.
|
|
</li>
|
|
<li>R27:
|
|
Pre-Kona mailing. Added new issues <a href="lwg-defects.html#404">404</a>-<a href="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="lwg-closed.html#390">390</a>-<a href="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="lwg-defects.html#253">253</a>, which has been given a new proposed resolution, were
|
|
moved to DR status. Added new issues <a href="lwg-defects.html#383">383</a>-<a href="lwg-defects.html#389">389</a>. (Issues <a href="lwg-active.html#387">387</a>-<a href="lwg-defects.html#389">389</a> were discussed
|
|
at the meeting.) Made progress on issues <a href="lwg-defects.html#225">225</a>, <a href="lwg-defects.html#226">226</a>, <a href="lwg-defects.html#229">229</a>: <a href="lwg-defects.html#225">225</a> and <a href="lwg-defects.html#229">229</a> have been moved to Ready status, and the only remaining
|
|
concerns with <a href="lwg-defects.html#226">226</a> involve wording.
|
|
</li>
|
|
<li>R23:
|
|
Pre-Santa Cruz mailing. Added new issues <a href="lwg-closed.html#367">367</a>-<a href="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="lwg-active.html#362">362</a>-<a href="lwg-active.html#366">366</a>.
|
|
</li>
|
|
<li>R21:
|
|
Pre-Curaçao mailing. Added new issues <a href="lwg-closed.html#351">351</a>-<a href="lwg-closed.html#361">361</a>.
|
|
</li>
|
|
<li>R20:
|
|
Post-Redmond mailing; reflects actions taken in Redmond. Added
|
|
new issues <a href="lwg-defects.html#336">336</a>-<a href="lwg-closed.html#350">350</a>, of which issues
|
|
<a href="lwg-defects.html#347">347</a>-<a href="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="lwg-defects.html#284">284</a>, <a href="lwg-defects.html#241">241</a>, and <a href="lwg-closed.html#267">267</a>.
|
|
|
|
Noteworthy issues discussed at Redmond include
|
|
<a href="lwg-defects.html#120">120</a> <a href="lwg-defects.html#202">202</a>, <a href="lwg-defects.html#226">226</a>, <a href="lwg-active.html#233">233</a>,
|
|
<a href="lwg-defects.html#270">270</a>, <a href="lwg-defects.html#253">253</a>, <a href="lwg-active.html#254">254</a>, <a href="lwg-closed.html#323">323</a>.
|
|
</li>
|
|
<li>R19:
|
|
Pre-Redmond mailing. Added new issues
|
|
<a href="lwg-closed.html#323">323</a>-<a href="lwg-defects.html#335">335</a>.
|
|
</li>
|
|
<li>R18:
|
|
Post-Copenhagen mailing; reflects actions taken in Copenhagen.
|
|
Added new issues <a href="lwg-defects.html#312">312</a>-<a href="lwg-defects.html#317">317</a>, and discussed
|
|
new issues <a href="lwg-defects.html#271">271</a>-<a href="lwg-closed.html#314">314</a>.
|
|
|
|
Changed status of issues
|
|
<a href="lwg-defects.html#103">103</a> <a href="lwg-defects.html#118">118</a> <a href="lwg-defects.html#136">136</a> <a href="lwg-defects.html#153">153</a>
|
|
<a href="lwg-defects.html#165">165</a> <a href="lwg-defects.html#171">171</a> <a href="lwg-defects.html#183">183</a> <a href="lwg-defects.html#184">184</a>
|
|
<a href="lwg-defects.html#185">185</a> <a href="lwg-defects.html#186">186</a> <a href="lwg-defects.html#214">214</a> <a href="lwg-defects.html#221">221</a>
|
|
<a href="lwg-defects.html#234">234</a> <a href="lwg-defects.html#237">237</a> <a href="lwg-defects.html#243">243</a> <a href="lwg-defects.html#248">248</a>
|
|
<a href="lwg-defects.html#251">251</a> <a href="lwg-defects.html#252">252</a> <a href="lwg-defects.html#256">256</a> <a href="lwg-defects.html#260">260</a>
|
|
<a href="lwg-defects.html#261">261</a> <a href="lwg-defects.html#262">262</a> <a href="lwg-defects.html#263">263</a> <a href="lwg-defects.html#265">265</a>
|
|
<a href="lwg-defects.html#268">268</a>
|
|
to DR.
|
|
|
|
Changed status of issues
|
|
<a href="lwg-defects.html#49">49</a> <a href="lwg-defects.html#109">109</a> <a href="lwg-defects.html#117">117</a> <a href="lwg-defects.html#182">182</a>
|
|
<a href="lwg-defects.html#228">228</a> <a href="lwg-defects.html#230">230</a> <a href="lwg-defects.html#232">232</a> <a href="lwg-defects.html#235">235</a>
|
|
<a href="lwg-defects.html#238">238</a> <a href="lwg-defects.html#241">241</a> <a href="lwg-defects.html#242">242</a> <a href="lwg-defects.html#250">250</a>
|
|
<a href="lwg-defects.html#259">259</a> <a href="lwg-defects.html#264">264</a> <a href="lwg-defects.html#266">266</a> <a href="lwg-closed.html#267">267</a>
|
|
<a href="lwg-defects.html#271">271</a> <a href="lwg-defects.html#272">272</a> <a href="lwg-defects.html#273">273</a> <a href="lwg-defects.html#275">275</a>
|
|
<a href="lwg-defects.html#281">281</a> <a href="lwg-defects.html#284">284</a> <a href="lwg-defects.html#285">285</a> <a href="lwg-defects.html#286">286</a>
|
|
<a href="lwg-defects.html#288">288</a> <a href="lwg-defects.html#292">292</a> <a href="lwg-defects.html#295">295</a> <a href="lwg-defects.html#297">297</a>
|
|
<a href="lwg-defects.html#298">298</a> <a href="lwg-defects.html#301">301</a> <a href="lwg-defects.html#303">303</a> <a href="lwg-defects.html#306">306</a>
|
|
<a href="lwg-defects.html#307">307</a> <a href="lwg-defects.html#308">308</a> <a href="lwg-defects.html#312">312</a>
|
|
to Ready.
|
|
|
|
Closed issues
|
|
<a href="lwg-closed.html#111">111</a> <a href="lwg-closed.html#277">277</a> <a href="lwg-closed.html#279">279</a> <a href="lwg-closed.html#287">287</a>
|
|
<a href="lwg-closed.html#289">289</a> <a href="lwg-closed.html#293">293</a> <a href="lwg-closed.html#302">302</a> <a href="lwg-closed.html#313">313</a>
|
|
<a href="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="lwg-defects.html#49">49</a>, <a href="lwg-defects.html#76">76</a>, <a href="lwg-defects.html#91">91</a>, <a href="lwg-defects.html#235">235</a>, <a href="lwg-defects.html#250">250</a>, <a href="lwg-closed.html#267">267</a>.
|
|
Added new issues <a href="lwg-defects.html#278">278</a>-<a href="lwg-defects.html#311">311</a>.
|
|
</li>
|
|
<li>R16:
|
|
post-Toronto mailing; reflects actions taken in Toronto. Added new
|
|
issues <a href="lwg-defects.html#265">265</a>-<a href="lwg-closed.html#277">277</a>. Changed status of issues
|
|
<a href="lwg-defects.html#3">3</a>, <a href="lwg-defects.html#8">8</a>, <a href="lwg-defects.html#9">9</a>, <a href="lwg-defects.html#19">19</a>,
|
|
<a href="lwg-defects.html#26">26</a>, <a href="lwg-defects.html#31">31</a>, <a href="lwg-defects.html#61">61</a>,
|
|
<a href="lwg-defects.html#63">63</a>, <a href="lwg-defects.html#86">86</a>, <a href="lwg-defects.html#108">108</a>,
|
|
<a href="lwg-defects.html#112">112</a>, <a href="lwg-defects.html#114">114</a>, <a href="lwg-defects.html#115">115</a>,
|
|
<a href="lwg-defects.html#122">122</a>, <a href="lwg-defects.html#127">127</a>, <a href="lwg-defects.html#129">129</a>,
|
|
<a href="lwg-defects.html#134">134</a>, <a href="lwg-defects.html#137">137</a>, <a href="lwg-defects.html#142">142</a>,
|
|
<a href="lwg-defects.html#144">144</a>, <a href="lwg-defects.html#146">146</a>, <a href="lwg-defects.html#147">147</a>,
|
|
<a href="lwg-defects.html#159">159</a>, <a href="lwg-defects.html#164">164</a>, <a href="lwg-defects.html#170">170</a>,
|
|
<a href="lwg-defects.html#181">181</a>, <a href="lwg-defects.html#199">199</a>, <a href="lwg-defects.html#208">208</a>,
|
|
<a href="lwg-defects.html#209">209</a>, <a href="lwg-defects.html#210">210</a>, <a href="lwg-defects.html#211">211</a>,
|
|
<a href="lwg-defects.html#212">212</a>, <a href="lwg-defects.html#217">217</a>, <a href="lwg-defects.html#220">220</a>,
|
|
<a href="lwg-defects.html#222">222</a>, <a href="lwg-defects.html#223">223</a>, <a href="lwg-defects.html#224">224</a>,
|
|
<a href="lwg-defects.html#227">227</a> to "DR". Reopened issue <a href="lwg-active.html#23">23</a>. Reopened
|
|
issue <a href="lwg-defects.html#187">187</a>. Changed issues <a href="lwg-closed.html#2">2</a> and
|
|
<a href="lwg-closed.html#4">4</a> to NAD. Fixed a typo in issue <a href="lwg-defects.html#17">17</a>. Fixed
|
|
issue <a href="lwg-defects.html#70">70</a>: signature should be changed both places it
|
|
appears. Fixed issue <a href="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="lwg-active.html#233">233</a>-<a href="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="lwg-defects.html#228">228</a> to <a href="lwg-defects.html#232">232</a>. (00-0019R1/N1242)
|
|
</li>
|
|
<li>R13:
|
|
pre-Tokyo II updated: Added issues <a href="lwg-defects.html#212">212</a> to <a href="lwg-defects.html#227">227</a>.
|
|
</li>
|
|
<li>R12:
|
|
pre-Tokyo II mailing: Added issues <a href="lwg-defects.html#199">199</a> to
|
|
<a href="lwg-defects.html#211">211</a>. Added "and paragraph 5" to the proposed resolution
|
|
of issue <a href="lwg-defects.html#29">29</a>. Add further rationale to issue
|
|
<a href="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="lwg-closed.html#4">4</a> and <a href="lwg-defects.html#38">38</a>. Added issues <a href="lwg-closed.html#196">196</a>
|
|
to <a href="lwg-defects.html#198">198</a>. Closed issues list split into "defects" and
|
|
"closed" documents. Changed the proposed resolution of issue
|
|
<a href="lwg-closed.html#4">4</a> to NAD, and changed the wording of proposed resolution
|
|
of issue <a href="lwg-defects.html#38">38</a>.
|
|
</li>
|
|
<li>R10:
|
|
pre-Kona updated. Added proposed resolutions <a href="lwg-defects.html#83">83</a>,
|
|
<a href="lwg-defects.html#86">86</a>, <a href="lwg-defects.html#91">91</a>, <a href="lwg-defects.html#92">92</a>,
|
|
<a href="lwg-defects.html#109">109</a>. Added issues <a href="lwg-closed.html#190">190</a> to
|
|
<a href="lwg-defects.html#195">195</a>. (99-0033/D1209, 14 Oct 99)
|
|
</li>
|
|
<li>R9:
|
|
pre-Kona mailing. Added issues <a href="lwg-closed.html#140">140</a> to
|
|
<a href="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="lwg-active.html#130">130</a>, <a href="lwg-closed.html#131">131</a>,
|
|
<a href="lwg-defects.html#132">132</a>, <a href="lwg-defects.html#133">133</a>, <a href="lwg-defects.html#134">134</a>,
|
|
<a href="lwg-closed.html#135">135</a>, <a href="lwg-defects.html#136">136</a>, <a href="lwg-defects.html#137">137</a>,
|
|
<a href="lwg-closed.html#138">138</a>, <a href="lwg-defects.html#139">139</a> (31 Mar 99)
|
|
</li>
|
|
<li>R6:
|
|
pre-Dublin mailing. Added issues <a href="lwg-defects.html#127">127</a>, <a href="lwg-closed.html#128">128</a>,
|
|
and <a href="lwg-defects.html#129">129</a>. (99-0007/N1194, 22 Feb 99)
|
|
</li>
|
|
<li>R5:
|
|
update issues <a href="lwg-defects.html#103">103</a>, <a href="lwg-defects.html#112">112</a>; added issues
|
|
<a href="lwg-defects.html#114">114</a> to <a href="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="lwg-defects.html#110">110</a>,
|
|
<a href="lwg-closed.html#111">111</a>, <a href="lwg-defects.html#112">112</a>, <a href="lwg-closed.html#113">113</a> added, several
|
|
issues corrected. (22 Oct 98)
|
|
</li>
|
|
<li>R3:
|
|
post-Santa Cruz II: Issues <a href="lwg-closed.html#94">94</a> to <a href="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="lwg-closed.html#73">73</a> to <a href="lwg-closed.html#93">93</a> added,
|
|
issue <a href="lwg-defects.html#17">17</a> updated. (29 Sep 98)
|
|
</li>
|
|
<li>R1:
|
|
Correction to issue <a href="lwg-defects.html#55">55</a> resolution, <a href="lwg-defects.html#60">60</a> code
|
|
format, <a href="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="lwg-active.html#New">New</a> when
|
|
they first appear on the issues list. They may progress to
|
|
<a href="lwg-active.html#Open">Open</a> or <a href="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="lwg-active.html#Dup">Dup</a>, <a href="lwg-active.html#NAD">NAD</a>, or <a href="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="lwg-active.html#DR">DR</a>). These in turn may
|
|
become the basis for Technical Corrigenda (<a href="lwg-active.html#TC">TC</a>),
|
|
or are closed without action other than a Record of Response
|
|
(<a href="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="lib-locales.html#lib.facet.num.get.virtuals"> [lib.facet.num.get.virtuals]</a> <b>Status:</b> <a href="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="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="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="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="lib-containers.html#lib.vector.bool"> [lib.vector.bool]</a> <b>Status:</b> <a href="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>
|
|
|
|
<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="lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a>, 23.1.1 <a href="lib-containers.html#lib.sequence.reqmts"> [lib.sequence.reqmts]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</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="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="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 an iterator pointing to the element immediately
|
|
following q2 prior to any elements being erased. If no such element
|
|
exists, a.end() is returned."
|
|
</p>
|
|
|
|
<p>
|
|
In 23.3.1 <a href="lib-containers.html#lib.map"> [lib.map]</a>, in the <tt>map</tt> class synopsis; and
|
|
in 23.3.2 <a href="lib-containers.html#lib.multimap"> [lib.multimap]</a>, in the <tt>multimap</tt> class synopsis; and
|
|
in 23.3.3 <a href="lib-containers.html#lib.set"> [lib.set]</a>, in the <tt>set</tt> class synopsis; and
|
|
in 23.3.4 <a href="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><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="lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a>, 23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a> <b>Status:</b> <a href="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="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="expr.html#expr.const"> [expr.const]</a>) that could ever meaningfully be passed to X::allocate</p>
|
|
|
|
<p>
|
|
Change 23.1 <a href="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="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="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="lib-support.html#lib.limits"> [lib.limits]</a> <b>Status:</b> <a href="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="lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a> <b>Status:</b> <a href="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="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="lib-containers.html#lib.vector.modifiers"> [lib.vector.modifiers]</a> <b>Status:</b> <a href="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="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="lib-diagnostics.html#lib.std.exceptions"> [lib.std.exceptions]</a> <b>Status:</b> <a href="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 is already 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="lib-diagnostics.html#lib.domain.error"> [lib.domain.error]</a> paragraph 3
|
|
and 19.1.6 <a href="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>
|
|
The copy constructors of all exception-derived classes already have a
|
|
no throw spec. Reference 18.6.1, 19.1 and 15.4/13.
|
|
</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.]</i></p>
|
|
|
|
<hr>
|
|
<a name="258"><h3>258. Missing allocator requirement</h3></a><p><b>Section:</b> 20.1.5 <a href="lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a> <b>Status:</b> <a href="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="lib-iterators.html#lib.reverse.iterators"> [lib.reverse.iterators]</a> <b>Status:</b> <a href="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="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="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="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="lib-algorithms.html#lib.alg.foreach"> [lib.alg.foreach]</a> <b>Status:</b> <a href="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="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="lib-intro.html#lib.macro.names"> [lib.macro.names]</a> <b>Status:</b> <a href="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="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="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="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="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="lib-iterators.html#lib.bidirectional.iterators"> [lib.bidirectional.iterators]</a>, 24.1.5 <a href="lib-iterators.html#lib.random.access.iterators"> [lib.random.access.iterators]</a> <b>Status:</b> <a href="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="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="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="lib-iostreams.html#lib.iostream.format"> [lib.iostream.format]</a> <b>Status:</b> <a href="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="lib-iostreams.html#lib.istream::sentry"> [lib.istream::sentry]</a>) and basic_ostream<>::sentry
|
|
(27.6.2.3 <a href="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="lwg-defects.html#195">195</a>, since
|
|
the function performs an input operation which may fail. However,
|
|
issue <a href="lwg-defects.html#195">195</a> amends 27.6.1.1.2 <a href="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="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="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="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="lib-iostreams.html#lib.istream.unformatted"> [lib.istream.unformatted]</a> <b>Status:</b> <a href="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="lwg-defects.html#60">60</a> which is now a dr, the
|
|
description of seekg in 27.6.1.3 <a href="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="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="lib-locales.html#lib.category.ctype"> [lib.category.ctype]</a> <b>Status:</b> <a href="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="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="lwg-defects.html#339">339</a> is related, but not identical. The
|
|
proposed resolution if issue <a href="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="lib-utilities.html#lib.bind.1st"> [lib.bind.1st]</a> <b>Status:</b> <a href="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="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="expr.html#expr.type.conv"> [expr.type.conv]</a>) is defined to be
|
|
semantically equivalent to an explicit cast expression (5.4 <a href="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="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="lib-iostreams.html#lib.input.output"> [lib.input.output]</a> <b>Status:</b> <a href="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="lib-strings.html#lib.string::replace"> [lib.string::replace]</a> <b>Status:</b> <a href="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="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="lib-iostreams.html#lib.iostream.objects"> [lib.iostream.objects]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</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>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="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a> <b>Status:</b> <a href="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="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="lib-iostreams.html#lib.stringbuf.virtuals"> [lib.stringbuf.virtuals]</a> <b>Status:</b> <a href="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="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="378"><h3>378. locale immutability and locale::operator=()</h3></a><p><b>Section:</b> 22.1.1 <a href="lib-locales.html#lib.locale"> [lib.locale]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 6 Sep 2002</p>
|
|
<p>
|
|
I think there is a problem with 22.1.1, p6 which says that
|
|
</p>
|
|
<pre>
|
|
-6- An instance of locale is immutable; once a facet reference
|
|
is obtained from it, that reference remains usable as long
|
|
as the locale value itself exists.
|
|
</pre>
|
|
<p>
|
|
and 22.1.1.2, p4:
|
|
</p>
|
|
<pre>
|
|
const locale& operator=(const locale& other) throw();
|
|
|
|
-4- Effects: Creates a copy of other, replacing the current value.
|
|
</pre>
|
|
<p>
|
|
How can a reference to a facet obtained from a locale object remain
|
|
valid after an assignment that clearly must replace all the facets
|
|
in the locale object? Imagine a program such as this
|
|
</p>
|
|
<pre>
|
|
std::locale loc ("de_DE");
|
|
const std::ctype<char> &r0 = std::use_facet<std::ctype<char> >(loc);
|
|
loc = std::locale ("en_US");
|
|
const std::ctype<char> &r1 = std::use_facet<std::ctype<char> >(loc);
|
|
</pre>
|
|
<p>
|
|
Is r0 really supposed to be preserved and destroyed only when loc goes
|
|
out of scope?
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p><i>[Summer '04 mid-meeting mailing: Martin and Dietmar believe this
|
|
is a duplicate of issue <a href="lwg-defects.html#31">31</a> and recommend that it be
|
|
closed.
|
|
]</i></p>
|
|
|
|
<hr>
|
|
<a name="382"><h3>382. codecvt do_in/out result</h3></a><p><b>Section:</b> 22.2.1.5 <a href="lib-locales.html#lib.locale.codecvt"> [lib.locale.codecvt]</a> <b>Status:</b> <a href="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="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="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="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="lib-algorithms.html#lib.equal.range"> [lib.equal.range]</a> <b>Status:</b> <a href="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="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="lib-intro.html#lib.library"> [lib.library]</a> <b>Status:</b> <a href="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="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="lib-algorithms.html#lib.algorithms"> [lib.algorithms]</a>
|
|
and 26 <a href="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="lib-iterators.html#lib.reverse.iter.opindex"> [lib.reverse.iter.opindex]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 23 Oct 2002</p>
|
|
<p>In 24.4.1.3.11 <a href="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="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="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>implementation defined</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="lib-numerics.html#lib.complex.numbers"> [lib.complex.numbers]</a> <b>Status:</b> <a href="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="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="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="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="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="lib-iostreams.html#lib.ostream.formatted.reqmts"> [lib.ostream.formatted.reqmts]</a> <b>Status:</b> <a href="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:
|
|
<pre>
|
|
... If the generation fails, then the formatted output function
|
|
does setstate(ios::failbit), which might throw an exception.
|
|
</pre>
|
|
</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>
|
|
<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>
|
|
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="lib-containers.html#lib.bitset.cons"> [lib.bitset.cons]</a> <b>Status:</b> <a href="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="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="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="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="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="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="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="lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a> <b>Status:</b> <a href="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="lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a> <b>Status:</b> <a href="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>
|
|
<pre>
|
|
basic_istream<charT, traits>&
|
|
get (char_type*, streamsize, char_type);
|
|
</pre>
|
|
</p>
|
|
<p>
|
|
Also sets failbit if it fails to extract any characters.
|
|
</p>
|
|
<p>
|
|
<pre>
|
|
basic_istream<charT, traits>&
|
|
get (char_type*, streamsize);
|
|
</pre>
|
|
</p>
|
|
<p>
|
|
Also sets failbit if it fails to extract any characters.
|
|
</p>
|
|
<p>
|
|
<pre>
|
|
basic_istream<charT, traits>&
|
|
getline (char_type*, streamsize, char_type);
|
|
</pre>
|
|
</p>
|
|
<p>
|
|
Also sets failbit if it fails to extract any characters.
|
|
</p>
|
|
<p>
|
|
<pre>
|
|
basic_istream<charT, traits>&
|
|
getline (char_type*, streamsize);
|
|
</pre>
|
|
</p>
|
|
<p>
|
|
Also sets failbit if it fails to extract any characters.
|
|
</p>
|
|
<p>
|
|
<pre>
|
|
basic_istream<charT, traits>&
|
|
ignore (int, int_type);
|
|
</pre>
|
|
</p>
|
|
<p>
|
|
<pre>
|
|
basic_istream<charT, traits>&
|
|
read (char_type*, streamsize);
|
|
</pre>
|
|
</p>
|
|
<p>
|
|
Also sets failbit if it encounters end-of-file.
|
|
</p>
|
|
<p>
|
|
<pre>
|
|
streamsize readsome (char_type*, streamsize);
|
|
</pre>
|
|
</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>
|
|
<pre>
|
|
int_type get();
|
|
</pre>
|
|
</p>
|
|
<p>
|
|
<pre>
|
|
basic_istream<charT, traits>&
|
|
get (char_type&);
|
|
</pre>
|
|
</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>
|
|
<pre>
|
|
basic_istream<charT, traits>&
|
|
get (basic_streambuf<charT, traits>&, char_type);
|
|
</pre>
|
|
</p>
|
|
<p>
|
|
<pre>
|
|
basic_istream<charT, traits>&
|
|
get (basic_streambuf<charT, traits>&);
|
|
</pre>
|
|
</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>
|
|
<pre>
|
|
int_type peek ();
|
|
</pre>
|
|
</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="lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a> <b>Status:</b> <a href="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="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="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="405"><h3>405. qsort and POD</h3></a><p><b>Section:</b> 25.4 <a href="lib-algorithms.html#lib.alg.c.library"> [lib.alg.c.library]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Ray Lischner <b>Date:</b> 08 Apr 2003</p>
|
|
<p>
|
|
Section 25.4 <a href="lib-algorithms.html#lib.alg.c.library"> [lib.alg.c.library]</a> describes bsearch and qsort, from the C
|
|
standard library. Paragraph 4 does not list any restrictions on qsort,
|
|
but it should limit the base parameter to point to POD. Presumably,
|
|
qsort sorts the array by copying bytes, which requires POD.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In 25.4 <a href="lib-algorithms.html#lib.alg.c.library"> [lib.alg.c.library]</a> paragraph 4, just after the declarations and
|
|
before the nonnormative note, add these words: "both of which have the
|
|
same behavior as the original declaration. The behavior is undefined
|
|
unless the objects in the array pointed to by <i>base</i> are of POD
|
|
type."
|
|
</p>
|
|
|
|
<p><i>[Something along these lines is clearly necessary. Matt
|
|
provided wording.]</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="lib-containers.html#lib.vector.modifiers"> [lib.vector.modifiers]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</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.2 <a href="lib-containers.html#lib.vector.capacity"> [lib.vector.capacity]</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, if first and last satisfy the forward iterator
|
|
requirements, an operation on first or last) there are no effects.
|
|
</blockquote>
|
|
|
|
<p><i>[Something along these lines is probably a good idea. It's
|
|
unclear why we're making a distinction between Input Iterators and
|
|
Forward Iterators.]</i></p>
|
|
|
|
<hr>
|
|
<a name="408"><h3>408. Is vector<reverse_iterator<char*> > forbidden?</h3></a><p><b>Section:</b> 24.1 <a href="lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a> <b>Status:</b> <a href="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="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="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="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="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="lib-iostreams.html#lib.ifstream.members"> [lib.ifstream.members]</a>, 27.8.1.10 <a href="lib-iostreams.html#lib.ofstream.members"> [lib.ofstream.members]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> Nathan Myers <b>Date:</b> 3 June 2003</p>
|
|
<p>
|
|
A strict reading of 27.8.1 <a href="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="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="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="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="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="410"><h3>410. Missing semantics for stack and queue comparison operators</h3></a><p><b>Section:</b> 23.2.3.1 <a href="lib-containers.html#lib.queue"> [lib.queue]</a>, 23.2.3.3 <a href="lib-containers.html#lib.stack"> [lib.stack]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Hans Bos <b>Date:</b> 7 Jun 2003</p>
|
|
<p>
|
|
Sections 23.2.3.1 <a href="lib-containers.html#lib.queue"> [lib.queue]</a> and 23.2.3.3 <a href="lib-containers.html#lib.stack"> [lib.stack]</a> list
|
|
comparison operators (==, !=, <, <=, >, =>) for queue and
|
|
stack. Only the semantics for queue::operator== (23.2.3.1 <a href="lib-containers.html#lib.queue"> [lib.queue]</a> par2) and queue::operator< (23.2.3.1 <a href="lib-containers.html#lib.queue"> [lib.queue]</a>
|
|
par3) are defined.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>Add the following new paragraphs after 23.2.3.1 <a href="lib-containers.html#lib.queue"> [lib.queue]</a>
|
|
paragraph 3:</p>
|
|
|
|
<blockquote>
|
|
|
|
<pre>
|
|
operator!=
|
|
</pre>
|
|
<p>Returns: <tt>x.c != y.c</tt></p>
|
|
|
|
<pre>
|
|
operator>
|
|
</pre>
|
|
<p>Returns: <tt>x.c > y.c</tt></p>
|
|
|
|
<pre>
|
|
operator<=
|
|
</pre>
|
|
<p>Returns: <tt>x.c <= y.c</tt></p>
|
|
|
|
<pre>
|
|
operator>=
|
|
</pre>
|
|
<p>Returns: <tt>x.c >= y.c</tt></p>
|
|
|
|
</blockquote>
|
|
|
|
<p>Add the following paragraphs at the end of 23.2.3.3 <a href="lib-containers.html#lib.stack"> [lib.stack]</a>:</p>
|
|
|
|
<blockquote>
|
|
|
|
<pre>
|
|
operator==
|
|
</pre>
|
|
<p>Returns: <tt>x.c == y.c</tt></p>
|
|
|
|
<pre>
|
|
operator<
|
|
</pre>
|
|
<p>Returns: <tt>x.c < y.c</tt></p>
|
|
|
|
<pre>
|
|
operator!=
|
|
</pre>
|
|
<p>Returns: <tt>x.c != y.c</tt></p>
|
|
|
|
<pre>
|
|
operator>
|
|
</pre>
|
|
<p>Returns: <tt>x.c > y.c</tt></p>
|
|
|
|
<pre>
|
|
operator<=
|
|
</pre>
|
|
<p>Returns: <tt>x.c <= y.c</tt></p>
|
|
|
|
<pre>
|
|
operator>=
|
|
</pre>
|
|
<p>Returns: <tt>x.c >= y.c</tt></p>
|
|
|
|
</blockquote>
|
|
|
|
|
|
<p><i>[Kona: Matt provided wording.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
There isn't any real doubt about what these operators are
|
|
supposed to do, but we ought to spell it out.
|
|
<hr>
|
|
<a name="412"><h3>412. Typo in 27.4.4.3</h3></a><p><b>Section:</b> 27.4.4.3 <a href="lib-iostreams.html#lib.iostate.flags"> [lib.iostate.flags]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 10 Jul 2003</p>
|
|
<p>
|
|
The Effects clause in 27.4.4.3 <a href="lib-iostreams.html#lib.iostate.flags"> [lib.iostate.flags]</a> paragraph 5 says that the
|
|
function only throws if the respective bits are already set prior to
|
|
the function call. That's obviously not the intent. The typo ought to
|
|
be corrected and the text reworded as: "If (<i>state</i> &
|
|
exceptions()) == 0, returns. ..."
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In 27.4.4.3 <a href="lib-iostreams.html#lib.iostate.flags"> [lib.iostate.flags]</a> paragraph 5, replace "If (rdstate() &
|
|
exceptions()) == 0" with "If ((state | (rdbuf() ? goodbit : badbit))
|
|
& exceptions()) == 0".
|
|
</p>
|
|
|
|
<p><i>[Kona: the original proposed resolution wasn't quite right. We
|
|
really do mean rdstate(); the ambiguity is that the wording in the
|
|
standard doesn't make it clear whether we mean rdstate() before
|
|
setting the new state, or rdsate() after setting it. We intend the
|
|
latter, of course. Post-Kona: Martin provided wording.]</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="lib-iostreams.html#lib.istream::extractors"> [lib.istream::extractors]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</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="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>
|
|
<hr>
|
|
<a name="415"><h3>415. behavior of std::ws</h3></a><p><b>Section:</b> 27.6.1.4 <a href="lib-iostreams.html#lib.istream.manip"> [lib.istream.manip]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 18 Sep 2003</p>
|
|
<p>
|
|
According to 27.6.1.4, the ws() manipulator is not required to construct
|
|
the sentry object. The manipulator is also not a member function so the
|
|
text in 27.6.1, p1 through 4 that describes the exception policy for
|
|
istream member functions does not apply. That seems inconsistent with
|
|
the rest of extractors and all the other input functions (i.e., ws will
|
|
not cause a tied stream to be flushed before extraction, it doesn't check
|
|
the stream's exceptions or catch exceptions thrown during input, and it
|
|
doesn't affect the stream's gcount).
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Add to 27.6.1.4 <a href="lib-iostreams.html#lib.istream.manip"> [lib.istream.manip]</a>, immediately before the first sentence
|
|
of paragraph 1, the following text:
|
|
</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 is.gcount(). After constructing a sentry
|
|
object...
|
|
</blockquote>
|
|
|
|
<p><i>[Post-Kona: Martin provided wording]</i></p>
|
|
|
|
<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="lib-support.html#lib.c.limits"> [lib.c.limits]</a> <b>Status:</b> <a href="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="lib-locales.html#lib.locale.ctype.virtuals"> [lib.locale.ctype.virtuals]</a> <b>Status:</b> <a href="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="lib-iostreams.html#lib.ios::Init"> [lib.ios::Init]</a> <b>Status:</b> <a href="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="lib-iostreams.html#lib.istream::sentry"> [lib.istream::sentry]</a> <b>Status:</b> <a href="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="lib-iostreams.html#lib.streambuf.cons"> [lib.streambuf.cons]</a> <b>Status:</b> <a href="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="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="lib-intro.html#lib.reserved.names"> [lib.reserved.names]</a> <b>Status:</b> <a href="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="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="lib-iostreams.html#lib.input.output"> [lib.input.output]</a> <b>Status:</b> <a href="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="lib-intro.html#lib.structure.summary"> [lib.structure.summary]</a> <b>Status:</b> <a href="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="425"><h3>425. return value of std::get_temporary_buffer</h3></a><p><b>Section:</b> 20.4.3 <a href="lib-utilities.html#lib.temporary.buffer"> [lib.temporary.buffer]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 18 Sep 2003</p>
|
|
<p>
|
|
The standard is not clear about the requirements on the value returned from
|
|
a call to get_temporary_buffer(0). In particular, it fails to specify whether
|
|
the call should return a distinct pointer each time it is called (like
|
|
operator new), or whether the value is unspecified (as if returned by
|
|
malloc). The standard also fails to mention what the required behavior
|
|
is when the argument is less than 0.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 20.4.3 <a href="lib-utilities.html#lib.temporary.buffer"> [lib.temporary.buffer]</a> paragraph 2 from "...or a pair of 0
|
|
values if no storage can be obtained" to "...or a pair of 0 values if
|
|
no storage can be obtained or if <i>n</i> <= 0."</p>
|
|
<p><i>[Kona: Matt provided wording]</i></p>
|
|
<hr>
|
|
<a name="426"><h3>426. search_n(), fill_n(), and generate_n() with negative n</h3></a><p><b>Section:</b> 25.1.9 <a href="lib-algorithms.html#lib.alg.search"> [lib.alg.search]</a>, 25.2.5 <a href="lib-algorithms.html#lib.alg.fill"> [lib.alg.fill]</a>, 25.2.6 <a href="lib-algorithms.html#lib.alg.generate"> [lib.alg.generate]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 18 Sep 2003</p>
|
|
<p>
|
|
The complexity requirements for these function templates are incorrect
|
|
(or don't even make sense) for negative n:</p>
|
|
|
|
<p>25.1.9, p7 (search_n):
|
|
<br>
|
|
Complexity: At most (last1 - first1) * count applications
|
|
of the corresponding predicate.</p>
|
|
|
|
<p>25.2.5, p3 (fill_n):
|
|
<br>
|
|
Complexity: Exactly last - first (or n) assignments.</p>
|
|
<br>
|
|
|
|
<p>25.2.6, p3 (generate_n):
|
|
<br>
|
|
Complexity: Exactly last - first (or n) assignments.</p>
|
|
|
|
<p>
|
|
In addition, the Requirements or the Effects clauses for the latter two
|
|
templates don't say anything about the behavior when n is negative.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 25.1.9, p7 to</p>
|
|
|
|
<blockquote>
|
|
Complexity: At most (last1 - first1) * count applications
|
|
of the corresponding predicate if count is positive,
|
|
or 0 otherwise.
|
|
</blockquote>
|
|
|
|
<p>Change 25.2.5, p2 to</p>
|
|
<blockquote>
|
|
Effects: Assigns value through all the iterators in the range [first,
|
|
last), or [first, first + n) if n is positive, none otherwise.
|
|
</blockquote>
|
|
|
|
<p>Change 25.2.5, p3 to:</p>
|
|
<blockquote>
|
|
Complexity: Exactly last - first (or n if n is positive,
|
|
or 0 otherwise) assignments.
|
|
</blockquote>
|
|
|
|
<p>
|
|
Change 25.2.6, p1
|
|
to (notice the correction for the misspelled "through"):
|
|
</p>
|
|
<blockquote>
|
|
Effects: Invokes the function object genand assigns the return
|
|
value of gen through all the iterators in the range [first, last),
|
|
or [first, first + n) if n is positive, or [first, first)
|
|
otherwise.
|
|
</blockquote>
|
|
|
|
<p>Change 25.2.6, p3 to:</p>
|
|
<blockquote>
|
|
Complexity: Exactly last - first (or n if n is positive,
|
|
or 0 otherwise) assignments.
|
|
</blockquote>
|
|
<p><b>Rationale:</b></p>
|
|
<p>Informally, we want to say that whenever we see a negative number
|
|
we treat it the same as if it were zero. We believe the above
|
|
changes do that (although they may not be the minimal way of saying
|
|
so). The LWG considered and rejected the alternative of saying that
|
|
negative numbers are undefined behavior.</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="lib-locales.html#lib.facet.num.get.virtuals"> [lib.facet.num.get.virtuals]</a> <b>Status:</b> <a href="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="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="lib-numerics.html#lib.valarray.sub"> [lib.valarray.sub]</a> <b>Status:</b> <a href="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="lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a>, 25 <a href="lib-algorithms.html#lib.algorithms"> [lib.algorithms]</a> <b>Status:</b> <a href="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="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="432"><h3>432. stringbuf::overflow() makes only one write position available</h3></a><p><b>Section:</b> 27.7.1.3 <a href="lib-iostreams.html#lib.stringbuf.virtuals"> [lib.stringbuf.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Christian W Brock <b>Date:</b> 24 Sep 2003</p>
|
|
<p>27.7.1.3 par 8 says:</p>
|
|
<blockquote>
|
|
Notes: The function can make a write position available only if
|
|
( mode & ios_base::out) != 0. To make a write position
|
|
available, the function reallocates (or initially allocates) an
|
|
array object with a sufficient number of elements to hold the
|
|
current array object (if any), plus one additional write position.
|
|
If ( mode & ios_base::in) != 0, the function alters the read end
|
|
pointer egptr() to point just past the new write position (as
|
|
does the write end pointer epptr()).
|
|
</blockquote>
|
|
|
|
<p>
|
|
The sentences "plus one additional write position." and especially
|
|
"(as does the write end pointer epptr())" COULD by interpreted
|
|
(and is interpreted by at least my library vendor) as:
|
|
</p>
|
|
|
|
<blockquote>
|
|
post-condition: epptr() == pptr()+1
|
|
</blockquote>
|
|
|
|
<p>
|
|
This WOULD force sputc() to call the virtual overflow() each time.
|
|
</p>
|
|
|
|
<p>The proposed change also affects Defect Report 169.</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>27.7.1.1/2 Change:</p>
|
|
|
|
<blockquote>
|
|
2- Notes: The function allocates no array object.
|
|
</blockquote>
|
|
|
|
<p>
|
|
to:
|
|
</p>
|
|
|
|
<blockquote>
|
|
2- Postcondition: str() == "".
|
|
</blockquote>
|
|
|
|
<p>
|
|
27.7.1.1/3 Change:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-3- Effects: Constructs an object of class basic_stringbuf,
|
|
initializing the base class with basic_streambuf()
|
|
(lib.streambuf.cons), and initializing mode with which . Then copies
|
|
the content of str into the basic_stringbuf underlying character
|
|
sequence and initializes the input and output sequences according to
|
|
which. If which & ios_base::out is true, initializes the output
|
|
sequence with the underlying sequence. If which & ios_base::in is
|
|
true, initializes the input sequence with the underlying sequence.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-3- Effects: Constructs an object of class basic_stringbuf,
|
|
initializing the base class with basic_streambuf()
|
|
(lib.streambuf.cons), and initializing mode with which. Then copies
|
|
the content of str into the basic_stringbuf underlying character
|
|
sequence. If which & ios_base::out is true, initializes the output
|
|
sequence such that pbase() points to the first underlying character,
|
|
epptr() points one past the last underlying character, and if (which &
|
|
ios_base::ate) is true, pptr() is set equal to
|
|
epptr() else pptr() is set equal to pbase(). If which & ios_base::in
|
|
is true, initializes the input sequence such that eback() and gptr()
|
|
point to the first underlying character and egptr() points one past
|
|
the last underlying character.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>27.7.1.2/1 Change:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-1- Returns: A basic_string object whose content is equal to the
|
|
basic_stringbuf underlying character sequence. If the buffer is only
|
|
created in input mode, the underlying character sequence is equal to
|
|
the input sequence; otherwise, it is equal to the output sequence. In
|
|
case of an empty underlying character sequence, the function returns
|
|
basic_string<charT,traits,Allocator>().
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-1- Returns: A basic_string object whose content is equal to the
|
|
basic_stringbuf underlying character sequence. If the basic_stringbuf
|
|
was created only in input mode, the resultant basic_string contains
|
|
the character sequence in the range [eback(), egptr()). If the
|
|
basic_stringbuf was created with (which & ios_base::out) being true
|
|
then the resultant basic_string contains the character sequence in the
|
|
range [pbase(), high_mark) where high_mark represents the position one
|
|
past the highest initialized character in the buffer. Characters can
|
|
be initialized either through writing to the stream, or by
|
|
constructing the basic_stringbuf with a basic_string, or by calling
|
|
the str(basic_string) member function. In the case of calling the
|
|
str(basic_string) member function, all characters initialized prior to
|
|
the call are now considered uninitialized (except for those
|
|
characters re-initialized by the new basic_string). Otherwise the
|
|
basic_stringbuf has been created in neither input nor output mode and
|
|
a zero length basic_string is returned.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>
|
|
27.7.1.2/2 Change:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-2- Effects: If the basic_stringbuf's underlying character sequence is
|
|
not empty, deallocates it. Then copies the content of s into the
|
|
basic_stringbuf underlying character sequence and initializes the
|
|
input and output sequences according to the mode stored when creating
|
|
the basic_stringbuf object. If (mode&ios_base::out) is true, then
|
|
initializes the output sequence with the underlying sequence. If
|
|
(mode&ios_base::in) is true, then initializes the input sequence with
|
|
the underlying sequence.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-2- Effects: Copies the content of s into the basic_stringbuf
|
|
underlying character sequence. If mode & ios_base::out is true,
|
|
initializes the output sequence such that pbase() points to the first
|
|
underlying character, epptr() points one past the last underlying
|
|
character, and if (mode & ios_base::ate) is true,
|
|
pptr() is set equal to epptr() else pptr() is set equal to pbase(). If
|
|
mode & ios_base::in is true, initializes the input sequence such that
|
|
eback() and gptr() point to the first underlying character and egptr()
|
|
points one past the last underlying character.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>Remove 27.2.1.2/3. (Same rationale as issue 238: incorrect and unnecessary.)</p>
|
|
|
|
<p>27.7.1.3/1 Change:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
1- Returns: If the input sequence has a read position available,
|
|
returns traits::to_int_type(*gptr()). Otherwise, returns
|
|
traits::eof().
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
1- Returns: If the input sequence has a read position available,
|
|
returns traits::to_int_type(*gptr()). Otherwise, returns
|
|
traits::eof(). Any character in the underlying buffer which has been
|
|
initialized is considered to be part of the input sequence.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>27.7.1.3/9 Change:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-9- Notes: The function can make a write position available only if (
|
|
mode & ios_base::out) != 0. To make a write position available, the
|
|
function reallocates (or initially allocates) an array object with a
|
|
sufficient number of elements to hold the current array object (if
|
|
any), plus one additional write position. If ( mode & ios_base::in) !=
|
|
0, the function alters the read end pointer egptr() to point just past
|
|
the new write position (as does the write end pointer epptr()).
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-9- The function can make a write position available only if ( mode &
|
|
ios_base::out) != 0. To make a write position available, the function
|
|
reallocates (or initially allocates) an array object with a sufficient
|
|
number of elements to hold the current array object (if any), plus one
|
|
additional write position. If ( mode & ios_base::in) != 0, the
|
|
function alters the read end pointer egptr() to point just past the
|
|
new write position.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>27.7.1.3/12 Change:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-12- _ If (newoff + off) < 0, or (xend - xbeg) < (newoff + off), the
|
|
positioning operation fails. Otherwise, the function assigns xbeg +
|
|
newoff + off to the next pointer xnext .
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
-12- _ If (newoff + off) < 0, or if (newoff + off) refers to an
|
|
uninitialized character (as defined in 27.7.1.2 <a href="lib-iostreams.html#lib.stringbuf.members"> [lib.stringbuf.members]</a>
|
|
paragraph 1), the positioning operation fails. Otherwise, the function
|
|
assigns xbeg + newoff + off to the next pointer xnext .
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p><i>[post-Kona: Howard provided wording. At Kona the LWG agreed that
|
|
something along these lines was a good idea, but the original
|
|
proposed resolution didn't say enough about the effect of various
|
|
member functions on the underlying character sequences.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>The current basic_stringbuf description is over-constrained in such
|
|
a way as to prohibit vendors from making this the high-performance
|
|
in-memory stream it was meant to be. The fundamental problem is that
|
|
the pointers: eback(), gptr(), egptr(), pbase(), pptr(), epptr() are
|
|
observable from a derived client, and the current description
|
|
restricts the range [pbase(), epptr()) from being grown geometrically.
|
|
This change allows, but does not require, geometric growth of this
|
|
range.</p>
|
|
|
|
<p>Backwards compatibility issues: These changes will break code that
|
|
derives from basic_stringbuf, observes epptr(), and depends upon
|
|
[pbase(), epptr()) growing by one character on each call to overflow()
|
|
(i.e. test suites). Otherwise there are no backwards compatibility
|
|
issues.</p>
|
|
|
|
<p>27.7.1.1/2: The non-normative note is non-binding, and if it were
|
|
binding, would be over specification. The recommended change focuses
|
|
on the important observable fact.</p>
|
|
|
|
<p>27.7.1.1/3: This change does two things: 1. It describes exactly
|
|
what must happen in terms of the sequences. The terms "input
|
|
sequence" and "output sequence" are not well defined. 2. It
|
|
introduces a common extension: open with app or ate mode. I concur
|
|
with issue 238 that paragraph 4 is both wrong and unnecessary.</p>
|
|
|
|
<p>27.7.1.2/1: This change is the crux of the efficiency issue. The
|
|
resultant basic_string is not dependent upon epptr(), and thus
|
|
implementors are free to grow the underlying buffer geometrically
|
|
during overflow() *and* place epptr() at the end of that buffer.</p>
|
|
|
|
<p>27.7.1.2/2: Made consistent with the proposed 27.7.1.1/3.</p>
|
|
|
|
<p>27.7.1.3/1: Clarifies that characters written to the stream beyond
|
|
the initially specified string are available for reading in an i/o
|
|
basic_streambuf.</p>
|
|
|
|
<p>27.7.1.3/9: Made normative by removing "Notes:", and removed the
|
|
trailing parenthetical comment concerning epptr().</p>
|
|
|
|
<p>27.7.1.3/12: Restricting the positioning to [xbeg, xend) is no
|
|
longer allowable since [pbase(), epptr()) may now contain
|
|
uninitialized characters. Positioning is only allowable over the
|
|
initialized range.</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="lib-containers.html#lib.bitset.members"> [lib.bitset.members]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</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="435"><h3>435. bug in DR 25</h3></a><p><b>Section:</b> 21.3.7.9 <a href="lib-strings.html#lib.string.io"> [lib.string.io]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 15 Oct 2003</p>
|
|
|
|
<p>
|
|
It has been pointed out that the proposed resolution in DR 25 may not be
|
|
quite up to snuff: <br>
|
|
http://gcc.gnu.org/ml/libstdc++/2003-09/msg00147.html
|
|
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#25<br>
|
|
</p>
|
|
|
|
<p>
|
|
It looks like Petur is right. The complete corrected text is copied below.
|
|
I think we may have have been confused by the reference to 22.2.2.2.2 and
|
|
the subsequent description of `n' which actually talks about the second
|
|
argument to sputn(), not about the number of fill characters to pad with.
|
|
</p>
|
|
|
|
<p>
|
|
So the question is: was the original text correct? If the intent was to
|
|
follow classic iostreams then it most likely wasn't, since setting width()
|
|
to less than the length of the string doesn't truncate it on output. This
|
|
is also the behavior of most implementations (except for SGI's standard
|
|
iostreams where the operator does truncate).
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the text in 21.3.7.9, p4 from</p>
|
|
<blockquote>
|
|
If bool(k) is true, inserts characters as if by calling
|
|
os.rdbuf()->sputn(str.data(), n), padding as described in stage 3
|
|
of lib.facet.num.put.virtuals, where n is the larger of os.width()
|
|
and str.size();
|
|
</blockquote>
|
|
<p>to</p>
|
|
<blockquote>
|
|
If bool(k) is true, determines padding as described in
|
|
lib.facet.num.put.virtuals, and then inserts the resulting
|
|
sequence of characters <tt>seq</tt> as if by calling
|
|
<tt>os.rdbuf()->sputn(seq, n)</tt>, where <tt>n</tt> is the larger of
|
|
<tt>os.width()</tt> and <tt>str.size()</tt>;
|
|
</blockquote>
|
|
|
|
<p><i>[Kona: it appears that neither the original wording, DR25, nor the
|
|
proposed resolution, is quite what we want. We want to say that
|
|
the string will be output, padded to os.width() if necessary. We
|
|
don't want to duplicate the padding rules in clause 22, because
|
|
they're complicated, but we need to be careful because they weren't
|
|
quite written with quite this case in mind. We need to say what
|
|
the character sequence is, and then defer to clause 22. Post-Kona:
|
|
Benjamin provided wording.]</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="lib-containers.html#lib.sequence.reqmts"> [lib.sequence.reqmts]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> Howard Hinnant <b>Date:</b> 20 Oct 2003</p>
|
|
|
|
<p>Section 23.1.1 <a href="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="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 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><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="441"><h3>441. Is fpos::state const?</h3></a><p><b>Section:</b> 27.4.3 <a href="lib-iostreams.html#lib.fpos"> [lib.fpos]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Vincent Leloup <b>Date:</b> 17 Nov 2003</p>
|
|
<p>
|
|
In section 27.4.3.1 <a href="lib-iostreams.html#lib.fpos.members"> [lib.fpos.members]</a> fpos<stateT>::state() is declared
|
|
non const, but in section 27.4.3 <a href="lib-iostreams.html#lib.fpos"> [lib.fpos]</a> it is declared const.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In section 27.4.3.1 <a href="lib-iostreams.html#lib.fpos.members"> [lib.fpos.members]</a>, change the declaration of
|
|
<tt>fpos<stateT>::state()</tt> to const.
|
|
</p>
|
|
<hr>
|
|
<a name="442"><h3>442. sentry::operator bool() inconsistent signature</h3></a><p><b>Section:</b> 27.6.2.3 <a href="lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Vincent Leloup <b>Date:</b> 18 Nov 2003</p>
|
|
<p>
|
|
In section 27.6.2.3 <a href="lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a> paragraph 4, in description part
|
|
basic_ostream<charT, traits>::sentry::operator bool() is declared
|
|
as non const, but in section 27.6.2.3, in synopsis it is declared
|
|
const.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In section 27.6.2.3 <a href="lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a> paragraph 4, change the declaration
|
|
of <tt>sentry::operator bool()</tt> to const.
|
|
</p>
|
|
<hr>
|
|
<a name="443"><h3>443. filebuf::close() inconsistent use of EOF</h3></a><p><b>Section:</b> 27.8.1.3 <a href="lib-iostreams.html#lib.filebuf.members"> [lib.filebuf.members]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Vincent Leloup <b>Date:</b> 20 Nov 2003</p>
|
|
<p>
|
|
In section 27.8.1.3 <a href="lib-iostreams.html#lib.filebuf.members"> [lib.filebuf.members]</a> par6, in effects description of
|
|
basic_filebuf<charT, traits>::close(), overflow(EOF) is used twice;
|
|
should be overflow(traits::eof()).
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Change overflow(EOF) to overflow(traits::eof()).
|
|
</p>
|
|
<hr>
|
|
<a name="444"><h3>444. Bad use of casts in fstream</h3></a><p><b>Section:</b> 27.8.1 <a href="lib-iostreams.html#lib.fstreams"> [lib.fstreams]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> Vincent Leloup <b>Date:</b> 20 Nov 2003</p>
|
|
<p>
|
|
27.8.1.7 <a href="lib-iostreams.html#lib.ifstream.members"> [lib.ifstream.members]</a> p1, 27.8.1.10 <a href="lib-iostreams.html#lib.ofstream.members"> [lib.ofstream.members]</a> p1, 27.8.1.13 <a href="lib-iostreams.html#lib.fstream.members"> [lib.fstream.members]</a> p1 seems have same problem as exposed in LWG issue
|
|
<a href="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="lib-iterators.html#lib.iterator.traits"> [lib.iterator.traits]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</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 <font color="red">24.3.1.1</font>, after:</p>
|
|
|
|
<blockquote>
|
|
be defined as the iterator's difference type, value type and iterator
|
|
category, respectively.
|
|
</blockquote>
|
|
|
|
<p>In <font color="red">24.3.1.1</font>, 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 <font color="red">24.3.1.1</font>, 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 <font color="red">24.5.6</font>, 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>[
|
|
Sydney: Agreed that this is under-specified, but it's not the only
|
|
place where iterators are under-specified. We may need a more complete
|
|
review. One nice simple rule that would solve this problem: *a is
|
|
always <tt>reference</tt> by definition, and a-> is
|
|
always <tt>pointer</tt> by definition. If we do that, then we'll also
|
|
have to change a few existing iterators (e.g. istreambuf_iterator) so
|
|
they conform to that rule. We need a review of how extensive those
|
|
changes would be. Or instead of fixing <tt>pointer</tt> we could
|
|
remove it. (Which would require changing reverse_iterator as part of
|
|
that change, since the present reverse_iterator relies on the
|
|
existence of <tt>pointer</tt>.) Jeremy will supply a more detailed
|
|
analysis for Redmond.
|
|
]</i></p>
|
|
|
|
<hr>
|
|
<a name="446"><h3>446. Iterator equality between different containers</h3></a><p><b>Section:</b> 24.1 <a href="lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a>, 23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a> <b>Status:</b> <a href="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="448"><h3>448. Random Access Iterators over abstract classes</h3></a><p><b>Section:</b> 24.1.5 <a href="lib-iterators.html#lib.random.access.iterators"> [lib.random.access.iterators]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 7 Jan 2004</p>
|
|
<p>
|
|
Table 76, the random access iterator requirement table, says that the
|
|
return type of a[n] must be "convertible to T". When an iterator's
|
|
value_type T is an abstract class, nothing is convertible to T.
|
|
Surely this isn't an intended restriction?
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Change the return type to "convertible to T const&".
|
|
</p>
|
|
<hr>
|
|
<a name="449"><h3>449. Library Issue 306 Goes Too Far</h3></a><p><b>Section:</b> 18.1 <a href="lib-support.html#lib.support.types"> [lib.support.types]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Pete Becker <b>Date:</b> 15 Jan 2004</p>
|
|
<p>Original text:</p>
|
|
<blockquote>
|
|
The macro offsetof accepts a restricted set of type arguments in this
|
|
International Standard. type shall be a POD structure or a POD union
|
|
(clause 9). The result of applying the offsetof macro to a field that
|
|
is a static data member or a function member is undefined."
|
|
</blockquote>
|
|
|
|
<p>Revised text:</p>
|
|
<blockquote>
|
|
"If type is not a POD structure or a POD union the results are undefined."
|
|
</blockquote>
|
|
|
|
<p>
|
|
Looks to me like the revised text should have replaced only the second
|
|
sentence. It doesn't make sense standing alone.
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 18.1, paragraph 5, to:</p>
|
|
|
|
<blockquote>
|
|
The macro offsetof accepts a restricted set of type arguments in this
|
|
International Standard. If type is not a POD structure or a POD union
|
|
the results are undefined. The result of applying the offsetof macro
|
|
to a field that is a static data member or a function member is
|
|
undefined."
|
|
</blockquote>
|
|
<hr>
|
|
<a name="452"><h3>452. locale::combine should be permitted to generate a named locale</h3></a><p><b>Section:</b> 22.1.1.3 <a href="lib-locales.html#lib.locale.members"> [lib.locale.members]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Bill Plauger <b>Date:</b> 30 Jan 2004</p>
|
|
<pre>
|
|
template<class Facet>
|
|
locale::combine(const locale&) const;
|
|
</pre>
|
|
<p>
|
|
is obliged to create a locale that has no name. This is overspecification
|
|
and overkill. The resulting locale should follow the usual rules -- it
|
|
has a name if the locale argument has a name and Facet is one of the
|
|
standard facets.
|
|
</p>
|
|
|
|
<p><i>[
|
|
Sydney and post-Sydney (see c++std-lib-13439, c++std-lib-13440,
|
|
c++std-lib-13443): agreed that it's overkill to say that the locale
|
|
is obligated to be nameless. However, we also can't require it to
|
|
have a name. At the moment, locale names are based on categories
|
|
and not on individual facets. If a locale contains two different
|
|
facets of different names from the same category, then this would
|
|
not fit into existing naming schemes. We need to give
|
|
implementations more freedom. Bill will provide wording.
|
|
]</i></p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p><b>Rationale:</b></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="lib-iostreams.html#lib.stringbuf.virtuals"> [lib.stringbuf.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</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>
|
|
<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="lib-iostreams.html#lib.filebuf.members"> [lib.filebuf.members]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</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>
|
|
<hr>
|
|
<a name="455"><h3>455. cerr::tie() and wcerr::tie() are overspecified</h3></a><p><b>Section:</b> 27.3 <a href="lib-iostreams.html#lib.iostream.objects"> [lib.iostream.objects]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</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><i>[Sydney: straw poll (3-1): we should <i>require</i>, not just
|
|
permit, cout and cerr to be tied on startup. 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="lib-intro.html#lib.headers"> [lib.headers]</a> <b>Status:</b> <a href="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="lib-containers.html#lib.bitset.cons"> [lib.bitset.cons]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</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="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="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="lib-iterators.html#lib.random.access.iterators"> [lib.random.access.iterators]</a> <b>Status:</b> <a href="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="lib-locales.html#lib.facet.num.get.virtuals"> [lib.facet.num.get.virtuals]</a> <b>Status:</b> <a href="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="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="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="lib-iostreams.html#lib.fstreams"> [lib.fstreams]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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>
|
|
</p>
|
|
<hr>
|
|
<a name="461"><h3>461. time_get hard or impossible to implement</h3></a><p><b>Section:</b> 22.2.5.1 <a href="lib-locales.html#lib.locale.time.get"> [lib.locale.time.get]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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>
|
|
</p>
|
|
<hr>
|
|
<a name="462"><h3>462. Destroying objects with static storage duration</h3></a><p><b>Section:</b> 3.6.3 <a href="basic.html#basic.start.term"> [basic.start.term]</a>, 18.3 <a href="lib-support.html#lib.support.start.term"> [lib.support.start.term]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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>
|
|
</p>
|
|
<hr>
|
|
<a name="463"><h3>463. auto_ptr usability issues</h3></a><p><b>Section:</b> 20.4.5 <a href="lib-utilities.html#lib.auto.ptr"> [lib.auto.ptr]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Rani Sharoni <b>Date:</b> 7 Dec 2003</p>
|
|
|
|
<p>
|
|
TC1 CWG DR #84 effectively made the template%lt;class Y> operator auto_ptr%lt;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 %lt;memory>
|
|
using std::auto_ptr;
|
|
|
|
struct B {};
|
|
struct D : B {};
|
|
|
|
auto_ptr%lt;D> source();
|
|
int sink(auto_ptr%lt;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%lt;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%lt;class Y> auto_ptr(auto_ptr%lt;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%lt;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%lt;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%lt;B>, std::string);
|
|
auto_ptr%lt;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%lt;B>::operator auto_ptr_ref%lt;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%lt;Y> that holds *this and this is another defect since
|
|
the type of *this is auto_ptr%lt;X> where X might be different from Y. Several
|
|
library vendors (e.g. SGI) implement auto_ptr_ref%lt;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%lt;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%lt;class Y> auto_ptr(auto_ptr%lt;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%lt;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%lt;class Y> auto_ptr(auto_ptr%lt;Y> const&) throw();
|
|
auto_ptr& operator=(auto_ptr&) throw();
|
|
template%lt;class Y> auto_ptr& operator=(auto_ptr%lt;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%lt;class U>
|
|
auto_ptr(U& rhs, typename
|
|
unspecified_error_on_const_auto_ptr%lt;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%lt;typename T> struct unspecified_error_on_const_auto_ptr;
|
|
|
|
template%lt;typename T>
|
|
struct unspecified_error_on_const_auto_ptr%lt;auto_ptr%lt;T> const>
|
|
{ typedef typename auto_ptr%lt;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%lt;X> from const auto_ptr%lt;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%lt;class Y> auto_ptr(auto_ptr%lt;Y> const& a) throw();</pre>
|
|
<p> 4 Requires: Y* can be implicitly converted to X*.</p>
|
|
<p> 5 Effects: Calls const_cast%lt;auto_ptr%lt;Y>&>(a).release().</p>
|
|
<p> 6 Postconditions: *this holds the pointer returned from a.release().</p>
|
|
|
|
<p>Change 20.4.5.1/10</p>
|
|
<pre>
|
|
template%lt;class Y> auto_ptr& operator=(auto_ptr%lt;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%lt;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%lt;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%lt;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%lt;Y> is
|
|
constructed from auto_ptr%lt;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>
|
|
</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="lib-containers.html#lib.vector"> [lib.vector]</a>, 23.3.1 <a href="lib-containers.html#lib.map"> [lib.map]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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>
|
|
</p>
|
|
<hr>
|
|
<a name="465"><h3>465. Contents of <ciso646></h3></a><p><b>Section:</b> 17.4.1.2 <a href="lib-intro.html#lib.headers"> [lib.headers]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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="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 a section somewhere (clause 18? clause 22?) that says <iso646.h> and <ciso646> are empty for C++.
|
|
</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="lib-strings.html#lib.string.cons"> [lib.string.cons]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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>
|
|
</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="lib-strings.html#lib.char.traits.specializations.char"> [lib.char.traits.specializations.char]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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>
|
|
<pre>
|
|
The two-argument members assign, eq, and lt are defined identically
|
|
to the built-in operators =, ==, and < respectively.
|
|
</pre>
|
|
<p>to</p>
|
|
<pre>
|
|
The two-argument members assign and eq are defined identically
|
|
to the built-in operators = and == respectively. The two-argument
|
|
member lt is defined identically to the built-in operator < for
|
|
type unsigned char.
|
|
</pre>
|
|
|
|
<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="lib-iostreams.html#lib.iostate.flags"> [lib.iostate.flags]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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>
|
|
|
|
<hr>
|
|
<a name="469"><h3>469. vector<bool> ill-formed relational operators</h3></a><p><b>Section:</b> 23.2.5 <a href="lib-containers.html#lib.vector.bool"> [lib.vector.bool]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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="lib-containers.html#lib.containers"> [lib.containers]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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>
|
|
|
|
<hr>
|
|
<a name="471"><h3>471. result of what() implementation-defined</h3></a><p><b>Section:</b> 18.6.1 <a href="lib-support.html#lib.exception"> [lib.exception]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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><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="lib-algorithms.html#lib.equal.range"> [lib.equal.range]</a> <b>Status:</b> <a href="lwg-active.html#New">New</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>
|
|
<hr>
|
|
<a name="473"><h3>473. underspecified ctype calls</h3></a><p><b>Section:</b> 22.2.1.1 <a href="lib-locales.html#lib.locale.ctype"> [lib.locale.ctype]</a> <b>Status:</b> <a href="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="lib-iostreams.html#lib.ostream.inserters.character"> [lib.ostream.inserters.character]</a> <b>Status:</b> <a href="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="lib-algorithms.html#lib.alg.foreach"> [lib.alg.foreach]</a> <b>Status:</b> <a href="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="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="lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a> <b>Status:</b> <a href="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="lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a> <b>Status:</b> <a href="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="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="lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a> <b>Status:</b> <a href="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="lwg-active.html#477">477</a></p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>----- End of document -----</p>
|
|
</body>
|
|
</html>
|