mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-28 00:45:27 +08:00
664ce87016
2002-11-21 Phil Edwards <pme@gcc.gnu.org> * docs/doxygen/style.css: Update. * docs/doxygen/user.cfg.in: Update. * docs/html/documentation.html: Regenerate. * docs/html/17_intro/howto.html: Tweak I/O sentry entry. * docs/html/27_io/howto.html: New section on headers. * docs/html/faq/index.html: Add i386 threading entry. * docs/html/faq/index.txt: Regenerate. * docs/html/ext/lwg-active.html, docs/html/ext/lwg-defects.html: Import R23. From-SVN: r59326
5989 lines
260 KiB
HTML
5989 lines
260 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">J16/02-0048 = WG21 N1390</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="left">Date:</td>
|
|
<td align="left">10 Sep 2002</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 23)</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 C++ FAQ at <a href="http://www.research.att.com/~austern/csc/faq.html">http://www.research.att.com/~austern/csc/faq.html</a>.
|
|
Public discussion of C++ Standard related issues occurs on <a href="news:comp.std.c%2B%2B">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>R23:
|
|
Pre-Santa Cruz mailing. Added new issues <a href="lwg-active.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-active.html#361">361</a>.
|
|
</li>
|
|
<li>R20:
|
|
Post-Redmond mailing; reflects actions taken in Redmond. Added
|
|
new issues <a href="lwg-active.html#336">336</a>-<a href="lwg-active.html#350">350</a>, of which issues
|
|
<a href="lwg-active.html#347">347</a>-<a href="lwg-active.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-active.html#241">241</a>, and <a href="lwg-closed.html#267">267</a>.
|
|
|
|
Noteworthy issues discussed at Redmond include
|
|
<a href="lwg-active.html#120">120</a> <a href="lwg-active.html#202">202</a>, <a href="lwg-active.html#226">226</a>, <a href="lwg-active.html#233">233</a>,
|
|
<a href="lwg-defects.html#270">270</a>, <a href="lwg-active.html#253">253</a>, <a href="lwg-active.html#254">254</a>, <a href="lwg-active.html#323">323</a>.
|
|
</li>
|
|
<li>R19:
|
|
Pre-Redmond mailing. Added new issues
|
|
<a href="lwg-active.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-active.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-active.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-active.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-active.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-active.html#91">91</a>, <a href="lwg-active.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-closed.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="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>PJP will provide wording.</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<hr>
|
|
<a name="44"><h3>44. Iostreams use operator== on int_type values</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> Nathan Myers <b>Date:</b> 6 Aug 1998</p>
|
|
<p>Many of the specifications for iostreams specify that character
|
|
values or their int_type equivalents are compared using operators ==
|
|
or !=, though in other places traits::eq() or traits::eq_int_type is
|
|
specified to be used throughout. This is an inconsistency; we should
|
|
change uses of == and != to use the traits members instead. </p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p><i>[Kona: Nathan to supply proposed wording]</i></p>
|
|
|
|
<p><i>[
|
|
Tokyo: the LWG reaffirmed that this is a defect, and requires careful
|
|
review of clause 27 as the changes are context sensitive.
|
|
]</i></p>
|
|
|
|
<hr>
|
|
<a name="91"><h3>91. Description of operator>> and getline() for string<> might cause endless loop</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> Nico Josuttis <b>Date:</b> 29 Sep 1998</p>
|
|
<p>Operator >> and getline() for strings read until eof()
|
|
in the input stream is true. However, this might never happen, if the
|
|
stream can't read anymore without reaching EOF. So shouldn't it be
|
|
changed into that it reads until !good() ? </p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 21.3.7.9 <a href="lib-strings.html#lib.string.io"> [lib.string.io]</a>, paragraph 1, replace:</p>
|
|
<blockquote>
|
|
Effects: Begins by constructing a sentry object k as if k were
|
|
constructed by typename basic_istream<charT,traits>::sentry k( is). If
|
|
bool( k) is true, it calls str.erase() and then extracts characters
|
|
from is and appends them to str as if by calling str.append(1, c). If
|
|
is.width() is greater than zero, the maximum number n of characters
|
|
appended is is.width(); otherwise n is str.max_size(). Characters are
|
|
extracted and appended until any of the following occurs:
|
|
</blockquote>
|
|
<p>with:</p>
|
|
<blockquote>
|
|
Effects: Behaves as a formatted input function (27.6.1.2.1 <a href="lib-iostreams.html#lib.istream.formatted.reqmts"> [lib.istream.formatted.reqmts]</a>). After constructing a sentry object, if the
|
|
sentry converts to true, calls str.erase() and then extracts
|
|
characters from is and appends them to str as if by calling
|
|
str.append(1,c). If is.width() is greater than zero, the maximum
|
|
number n of characters appended is is.width(); otherwise n is
|
|
str.max_size(). Characters are extracted and appended until any of the
|
|
following occurs:
|
|
</blockquote>
|
|
|
|
<p>In 21.3.7.9 <a href="lib-strings.html#lib.string.io"> [lib.string.io]</a>, paragraph 6, replace</p>
|
|
<blockquote>
|
|
Effects: Begins by constructing a sentry object k as if by typename
|
|
basic_istream<charT,traits>::sentry k( is, true). If bool( k) is true,
|
|
it calls str.erase() and then extracts characters from is and appends
|
|
them to str as if by calling str.append(1, c) until any of the
|
|
following occurs:
|
|
</blockquote>
|
|
<p>with:</p>
|
|
<blockquote>
|
|
Effects: Behaves as an unformatted input function (27.6.1.3 <a href="lib-iostreams.html#lib.istream.unformatted"> [lib.istream.unformatted]</a>), except that it does not affect the value returned
|
|
by subsequent calls to basic_istream<>::gcount(). After
|
|
constructing a sentry object, if the sentry converts to true, calls
|
|
str.erase() and then extracts characters from is and appends them to
|
|
str as if by calling str.append(1,c) until any of the following
|
|
occurs:
|
|
</blockquote>
|
|
|
|
<p><i>[Redmond: Made changes in proposed resolution. <tt>operator>></tt>
|
|
should be a formatted input function, not an unformatted input function.
|
|
<tt>getline</tt> should not be required to set <tt>gcount</tt>, since
|
|
there is no mechanism for <tt>gcount</tt> to be set except by one of
|
|
<tt>basic_istream</tt>'s member functions.]</i></p>
|
|
|
|
<p><i>[Curaçao: Nico agrees with proposed resolution.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>The real issue here is whether or not these string input functions
|
|
get their characters from a streambuf, rather than by calling an
|
|
istream's member functions, a streambuf signals failure either by
|
|
returning eof or by throwing an exception; there are no other
|
|
possibilities. The proposed resolution makes it clear that these two
|
|
functions do get characters from a streambuf.</p>
|
|
<hr>
|
|
<a name="92"><h3>92. Incomplete Algorithm Requirements</h3></a><p>
|
|
<b>Section:</b> 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> Nico Josuttis <b>Date:</b> 29 Sep 1998</p>
|
|
<p>The standard does not state, how often a function object is copied,
|
|
called, or the order of calls inside an algorithm. This may lead to
|
|
surprising/buggy behavior. Consider the following example: </p>
|
|
|
|
<pre>class Nth { // function object that returns true for the nth element
|
|
private:
|
|
int nth; // element to return true for
|
|
int count; // element counter
|
|
public:
|
|
Nth (int n) : nth(n), count(0) {
|
|
}
|
|
bool operator() (int) {
|
|
return ++count == nth;
|
|
}
|
|
};
|
|
....
|
|
// remove third element
|
|
list<int>::iterator pos;
|
|
pos = remove_if(coll.begin(),coll.end(), // range
|
|
Nth(3)), // remove criterion
|
|
coll.erase(pos,coll.end()); </pre>
|
|
|
|
<p>This call, in fact removes the 3rd <b>AND the 6th</b> element. This
|
|
happens because the usual implementation of the algorithm copies the
|
|
function object internally: </p>
|
|
|
|
<pre>template <class ForwIter, class Predicate>
|
|
ForwIter std::remove_if(ForwIter beg, ForwIter end, Predicate op)
|
|
{
|
|
beg = find_if(beg, end, op);
|
|
if (beg == end) {
|
|
return beg;
|
|
}
|
|
else {
|
|
ForwIter next = beg;
|
|
return remove_copy_if(++next, end, beg, op);
|
|
}
|
|
} </pre>
|
|
|
|
<p>The algorithm uses find_if() to find the first element that should
|
|
be removed. However, it then uses a copy of the passed function object
|
|
to process the resulting elements (if any). Here, Nth is used again
|
|
and removes also the sixth element. This behavior compromises the
|
|
advantage of function objects being able to have a state. Without any
|
|
cost it could be avoided (just implement it directly instead of
|
|
calling find_if()). </p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p> In [lib.function.objects] 20.3 Function objects add as new
|
|
paragraph 6 (or insert after paragraph 1): </p>
|
|
|
|
<p>Option 1: </p>
|
|
<blockquote>
|
|
Predicates are functions or function objects that fulfill the
|
|
following requirements:<br> - They return a Boolean value (bool
|
|
or a value convertible to bool)<br> - It doesn't matter for the
|
|
behavior of a predicate how often it is copied or assigned and how
|
|
often it is called.
|
|
</blockquote>
|
|
|
|
<p>Option 2: </p>
|
|
<blockquote>
|
|
- if it's a function:<br> - All calls with the same
|
|
argument values yield the same result.<br> - if it's a function
|
|
object:<br> - In any sequence of calls to operator () without
|
|
calling any non-constant member function, all calls with the same
|
|
argument values yield the same result. <br> - After an assignment
|
|
or copy both objects return the same result for the same values.
|
|
</blockquote>
|
|
|
|
<p><i>[Santa Cruz: The LWG believes that there may be more to this than
|
|
meets the eye. It applies to all function objects, particularly
|
|
predicates. Two questions: (1) must a function object be
|
|
copyable? (2) how many times is a function object called? These
|
|
are in effect questions about state. Function objects appear to
|
|
require special copy semantics to make state work, and may fail if
|
|
calling alters state and calling occurs an unexpected number of
|
|
times.]</i></p>
|
|
|
|
<p><i>[Dublin: Pete Becker felt that this may not be a defect,
|
|
but rather something that programmers need to be educated about.
|
|
There was discussion of adding wording to the effect that the number
|
|
and order of calls to function objects, including predicates, not
|
|
affect the behavior of the function object.]</i></p>
|
|
|
|
<p><i>[Pre-Kona: Nico comments: It seems the problem is that we don't
|
|
have a clear statement of "predicate" in the
|
|
standard. People including me seemed to think "a function
|
|
returning a Boolean value and being able to be called by an STL
|
|
algorithm or be used as sorting criterion or ... is a
|
|
predicate". But a predicate has more requirements: It should
|
|
never change its behavior due to a call or being copied. IMHO we have
|
|
to state this in the standard. If you like, see section 8.1.4 of my
|
|
library book for a detailed discussion.]</i></p>
|
|
|
|
<p><i>[Kona: Nico will provide wording to the effect that "unless
|
|
otherwise specified, the number of copies of and calls to function
|
|
objects by algorithms is unspecified". Consider placing in
|
|
25 <a href="lib-algorithms.html#lib.algorithms"> [lib.algorithms]</a> after paragraph 9.]</i></p>
|
|
|
|
<p><i>[Pre-Tokyo: Angelika Langer comments: if the resolution is
|
|
that algorithms are free to copy and pass around any function objects,
|
|
then it is a valid question whether they are also allowed to change
|
|
the type information from reference type to value type.]</i></p>
|
|
|
|
<p><i>[Tokyo: Nico will discuss this further with Matt as there are
|
|
multiple problems beyond the underlying problem of no definition of
|
|
"Predicate".]</i></p>
|
|
|
|
<p><i>[Post-Tokyo: Nico provided the above proposed
|
|
resolutions.]</i></p>
|
|
|
|
<p><i>[Curaçao: Nico will provide wording to make options clearer: are
|
|
the exclusive, or is one a superset of the other?]</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="98"><h3>98. Input iterator requirements are badly written</h3></a><p>
|
|
<b>Section:</b> 24.1.1 <a href="lib-iterators.html#lib.input.iterators"> [lib.input.iterators]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> AFNOR <b>Date:</b> 7 Oct 1998</p>
|
|
<p>Table 72 in 24.1.1 <a href="lib-iterators.html#lib.input.iterators"> [lib.input.iterators]</a> specifies semantics for
|
|
<tt>*r++</tt> of:</p>
|
|
|
|
<p> <tt>{ T tmp = *r; ++r; return tmp; }</tt>
|
|
</p>
|
|
|
|
<p>There are two problems with this. First, the return type is
|
|
specified to be "T", as opposed to something like "convertible to T".
|
|
This is too specific: we want to allow *r++ to return an lvalue.</p>
|
|
|
|
<p>Second, writing the semantics in terms of code misleadingly
|
|
suggests that the effects *r++ should precisely replicate the behavior
|
|
of this code, including side effects. (What if it's a user-defined
|
|
type whose copy constructor has observable behavior?) We should
|
|
replace the code with words, or else put some blanket statement in
|
|
clause 17 saying that code samples aren't intended to specify exactly
|
|
how many times a copy constructor is called, even if the copy
|
|
constructor has observable behavior. (See issue <a href="lwg-active.html#334">334</a>
|
|
for a similar problem.)</p>
|
|
|
|
<p><i>[Issue still isn't clear. Matt will try to explain it more
|
|
clearly at the next meeting.]</i></p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<hr>
|
|
<a name="120"><h3>120. Can an implementor add specializations?</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> Judy Ward <b>Date:</b> 15 Dec 1998</p>
|
|
|
|
<p>The original issue asked whether a library implementor could
|
|
specialize standard library templates for built-in types. (This was
|
|
an issue because users are permitted to explicitly instantiate
|
|
standard library templates.)</p>
|
|
|
|
<p>Specializations are no longer a problem, because of the resolution
|
|
to core issue 259. Under the proposed resolution, it will be legal
|
|
for a translation unit to contain both a specialization and an
|
|
explicit instantiation of the same template, provided that the
|
|
specialization comes first. In such a case, the explicit
|
|
instantiation will be ignored. Further discussion of library issue
|
|
120 assumes that the core 259 resolution will be adopted.</p>
|
|
|
|
<p>However, as noted in lib-7047, one piece of this issue still
|
|
remains: what happens if a standard library implementor explicitly
|
|
instantiates a standard library templates? It's illegal for a program
|
|
to contain two different explicit instantiations of the same template
|
|
for the same type in two different translation units (ODR violation),
|
|
and the core working group doesn't believe it is practical to relax
|
|
that restriction.</p>
|
|
|
|
<p>The issue, then, is: are users allowed to implicitly instantiate
|
|
standard library templates for non-user defined types? The status quo
|
|
answer is 'yes'. Changing it to 'no' would give library implementors
|
|
more freedom.</p>
|
|
|
|
<p>This is an issue because, for performance reasons, library
|
|
implementors often need to explicitly instantiate standard library
|
|
templates. (for example, std::basic_string<char>) Does giving
|
|
users freedom to explicitly instantiate standard library templates for
|
|
non-user defined types make it impossible or painfully difficult for
|
|
library implementors to do this?</p>
|
|
|
|
<p>John Spicer suggests, in lib-8957, that library implementors have a
|
|
mechanism they can use for explicit instantiations that doesn't
|
|
prevent users from performing their own explicit instantiations: put
|
|
each explicit instantiation in its own object file. (Different
|
|
solutions might be necessary for Unix DSOs or MS-Windows DLLs.) On
|
|
some platforms, library implementors might not need to do anything
|
|
special: the "undefined behavior" that results from having two
|
|
different explicit instantiations might be harmless.</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Option 1.</p>
|
|
<blockquote>
|
|
<p>Append to 17.4.3.1 <a href="lib-intro.html#lib.reserved.names"> [lib.reserved.names]</a> paragraph 1: </p>
|
|
<blockquote>
|
|
A program may explicitly instantiate any templates in the standard
|
|
library only if the declaration depends on a user-defined name of
|
|
external linkage and the instantiation meets the standard library
|
|
requirements for the original template.
|
|
</blockquote>
|
|
</blockquote>
|
|
|
|
<p>Option 2.</p>
|
|
<blockquote>
|
|
<p>In light of the resolution to core issue 259, no normative changes
|
|
in the library clauses are necessary. Add the following non-normative
|
|
note to the end of 17.4.3.1 <a href="lib-intro.html#lib.reserved.names"> [lib.reserved.names]</a> paragraph 1:</p>
|
|
<blockquote>
|
|
[<i>Note:</i> A program may explicitly instantiate standard library
|
|
templates, even when an explicit instantiation does not depend on
|
|
a user-defined name. <i>--end note</i>]
|
|
</blockquote>
|
|
</blockquote>
|
|
|
|
<p><i>[Copenhagen: LWG discussed three options. (1) Users may not
|
|
explicitly instantiate standard library templates, except on
|
|
user-defined types. Consequence: library implementors may freely
|
|
specialize or instantiate templates. (2) Users may explicitly
|
|
instantiate any standard library template. Consequence: if
|
|
implementors specialize or instantiate library templates, they may
|
|
need to take special steps to make sure users can do it too. (3) It
|
|
is implementation defined whether users may explicitly instantiate
|
|
standard library templates on non-user-defined types. Consequence:
|
|
library implementors may freely specialize or instantiate templates,
|
|
but may need to document some or all templates that have been
|
|
explicitly instantiated.
|
|
]</i></p>
|
|
|
|
<p><i>[Straw poll (first number is favor, second is strongly oppose): 1
|
|
- 4, 0; 2 - 9, 1; 3 - 0, 9. (Proposed resolution 1 was the original
|
|
proposed resolution.) Because there was no support for option 3, no
|
|
wording is provided.]</i></p>
|
|
|
|
<p><i>[Redmond: discussed again; straw poll had results similar to
|
|
those of Copenhagen (1 - 1, 3; 2 - 8, 4; 3 - 6, 2). Most people said
|
|
they could live with any option. The only objection to option 2 is
|
|
potential implementation difficulty. Steve Clamage volunteered do a
|
|
survey to see if there are any popular platforms where option 2 would
|
|
present a real problem for implementors. See his reflector message,
|
|
c++std-lib-9002.
|
|
]</i></p>
|
|
|
|
<p><i>[Steve and Pete Becker will talk to Jonathan Caves. The
|
|
Microsoft linker might present a problem if there are multiple copies,
|
|
some of which have static data and some of which are in DLLs. There
|
|
may be similar problems with the Apple linker; Matt will clarify
|
|
that.]</i></p>
|
|
|
|
<hr>
|
|
<a name="123"><h3>123. Should valarray helper arrays fill functions be const?</h3></a><p>
|
|
<b>Section:</b> 26.3.5.4 <a href="lib-numerics.html#lib.slice.arr.fill"> [lib.slice.arr.fill]</a>, 26.3.7.4 <a href="lib-numerics.html#lib.gslice.array.fill"> [lib.gslice.array.fill]</a>, 26.3.8.4 <a href="lib-numerics.html#lib.mask.array.fill"> [lib.mask.array.fill]</a>, 26.3.9.4 <a href="lib-numerics.html#lib.indirect.array.fill"> [lib.indirect.array.fill]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Judy Ward <b>Date:</b> 15 Dec 1998 </p>
|
|
<p>One of the operator= in the valarray helper arrays is const and one
|
|
is not. For example, look at slice_array. This operator= in Section
|
|
26.3.5.2 <a href="lib-numerics.html#lib.slice.arr.assign"> [lib.slice.arr.assign]</a> is const: </p>
|
|
|
|
<p> <tt>void operator=(const valarray<T>&) const;</tt> </p>
|
|
|
|
<p>but this one in Section 26.3.5.4 <a href="lib-numerics.html#lib.slice.arr.fill"> [lib.slice.arr.fill]</a> is not: </p>
|
|
|
|
<p> <tt>void operator=(const T&); </tt>
|
|
</p>
|
|
|
|
<p>The description of the semantics for these two functions is similar. </p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>26.3.5 <a href="lib-numerics.html#lib.template.slice.array"> [lib.template.slice.array]</a> Template class slice_array</p>
|
|
<blockquote>
|
|
|
|
<p>In the class template definition for slice_array, replace the member
|
|
function declaration</p>
|
|
<pre>
|
|
void operator=(const T&);
|
|
</pre>
|
|
<p>with</p>
|
|
<pre>
|
|
void operator=(const T&) const;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>26.3.5.4 <a href="lib-numerics.html#lib.slice.arr.fill"> [lib.slice.arr.fill]</a> slice_array fill function</p>
|
|
<blockquote>
|
|
|
|
<p>Change the function declaration</p>
|
|
<pre>
|
|
void operator=(const T&);
|
|
</pre>
|
|
<p>to</p>
|
|
<pre>
|
|
void operator=(const T&) const;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>26.3.7 <a href="lib-numerics.html#lib.template.gslice.array"> [lib.template.gslice.array]</a> Template class gslice_array</p>
|
|
<blockquote>
|
|
|
|
<p>In the class template definition for gslice_array, replace the member
|
|
function declaration</p>
|
|
<pre>
|
|
void operator=(const T&);
|
|
</pre>
|
|
<p>with</p>
|
|
<pre>
|
|
void operator=(const T&) const;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>26.3.7.4 <a href="lib-numerics.html#lib.gslice.array.fill"> [lib.gslice.array.fill]</a> gslice_array fill function</p>
|
|
<blockquote>
|
|
|
|
<p>Change the function declaration</p>
|
|
<pre>
|
|
void operator=(const T&);
|
|
</pre>
|
|
<p>to</p>
|
|
<pre>
|
|
void operator=(const T&) const;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>26.3.8 <a href="lib-numerics.html#lib.template.mask.array"> [lib.template.mask.array]</a> Template class mask_array</p>
|
|
<blockquote>
|
|
|
|
<p>In the class template definition for mask_array, replace the member
|
|
function declaration</p>
|
|
<pre>
|
|
void operator=(const T&);
|
|
</pre>
|
|
<p>with</p>
|
|
<pre>
|
|
void operator=(const T&) const;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>26.3.8.4 <a href="lib-numerics.html#lib.mask.array.fill"> [lib.mask.array.fill]</a> mask_array fill function</p>
|
|
<blockquote>
|
|
|
|
<p>Change the function declaration</p>
|
|
<pre>
|
|
void operator=(const T&);
|
|
</pre>
|
|
<p>to</p>
|
|
<pre>
|
|
void operator=(const T&) const;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>26.3.9 <a href="lib-numerics.html#lib.template.indirect.array"> [lib.template.indirect.array]</a> Template class indirect_array</p>
|
|
<blockquote>
|
|
|
|
<p>In the class template definition for indirect_array, replace the member
|
|
function declaration</p>
|
|
<pre>
|
|
void operator=(const T&);
|
|
</pre>
|
|
<p>with</p>
|
|
<pre>
|
|
void operator=(const T&) const;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>26.3.9.4 <a href="lib-numerics.html#lib.indirect.array.fill"> [lib.indirect.array.fill]</a> indirect_array fill function</p>
|
|
<blockquote>
|
|
|
|
<p>Change the function declaration</p>
|
|
<pre>
|
|
void operator=(const T&);
|
|
</pre>
|
|
<p>to</p>
|
|
<pre>
|
|
void operator=(const T&) const;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
|
|
<p><i>[Redmond: Robert provided wording.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>There's no good reason for one version of operator= being const and
|
|
another one not. Because of issue <a href="lwg-active.html#253">253</a>, this now
|
|
matters: these functions are now callable in more circumstances. In
|
|
many existing implementations, both versions are already const.</p>
|
|
<hr>
|
|
<a name="167"><h3>167. Improper use of <tt>traits_type::length()</tt>
|
|
</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#Open">Open</a> <b>Submitter:</b> Dietmar Kühl <b>Date:</b> 20 Jul 1999</p>
|
|
<p>Paragraph 4 states that the length is determined using
|
|
<tt>traits::length(s)</tt>. Unfortunately, this function is not
|
|
defined for example if the character type is <tt>wchar_t</tt> and the
|
|
type of <tt>s</tt> is <tt>char const*</tt>. Similar problems exist if
|
|
the character type is <tt>char</tt> and the type of <tt>s</tt> is
|
|
either <tt>signed char const*</tt> or <tt>unsigned char
|
|
const*</tt>.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 27.6.2.5.4 <a href="lib-iostreams.html#lib.ostream.inserters.character"> [lib.ostream.inserters.character]</a> paragraph 4 from:</p>
|
|
<blockquote>
|
|
<p>Effects: Behaves like an formatted inserter (as described in
|
|
lib.ostream.formatted.reqmts) of out. After a sentry object is
|
|
constructed it inserts characters. The number of characters starting
|
|
at s to be inserted is traits::length(s). Padding is determined as
|
|
described in lib.facet.num.put.virtuals. The traits::length(s)
|
|
characters starting at s are widened using out.widen
|
|
(lib.basic.ios.members). The widened characters and any required
|
|
padding are inserted into out. Calls width(0).</p>
|
|
</blockquote>
|
|
<p>to:</p>
|
|
<blockquote>
|
|
<p>Effects: Behaves like an formatted inserter (as described in
|
|
lib.ostream.formatted.reqmts) of out. After a sentry object is
|
|
constructed it inserts characters. The number len of characters
|
|
starting at s to be inserted is</p>
|
|
<p>
|
|
- traits::length((const char*)s) if the second argument is of type
|
|
const charT*<br>
|
|
- char_traits<char>::length(s) if the second argument is of
|
|
type const char*, const signed char*, or const unsigned char* and
|
|
and charT is not char.<br>
|
|
</p>
|
|
<p>Padding is determined as described in
|
|
lib.facet.num.put.virtuals. The len characters starting at s are
|
|
widened using out.widen (lib.basic.ios.members). The widened
|
|
characters and any required padding are inserted into out. Calls
|
|
width(0).</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Kona: It is clear to the LWG there is a defect here.
|
|
Dietmar will supply specific wording.]</i></p>
|
|
|
|
<p><i>[Post-Tokyo: Dietmar supplied the above wording.]</i></p>
|
|
|
|
<p><i>[Toronto: The original proposed resolution involved
|
|
char_traits<signed char> and char_traits<unsigned char>.
|
|
There was strong opposition to requiring that library implementors
|
|
provide those specializations of char_traits.]</i></p>
|
|
|
|
<p><i>[Copenhagen: This still isn't quite right: proposed resolution
|
|
text got garbled when the signed char/unsigned char specializations
|
|
were removed. Dietmar will provide revised wording.]</i></p>
|
|
<hr>
|
|
<a name="179"><h3>179. Comparison of const_iterators to iterators doesn't work</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#Ready">Ready</a> <b>Submitter:</b> Judy Ward <b>Date:</b> 2 Jul 1998</p>
|
|
<p>Currently the following will not compile on two well-known standard
|
|
library implementations:</p>
|
|
|
|
<blockquote>
|
|
<pre>#include <set>
|
|
using namespace std;
|
|
|
|
void f(const set<int> &s)
|
|
{
|
|
set<int>::iterator i;
|
|
if (i==s.end()); // s.end() returns a const_iterator
|
|
}</pre>
|
|
</blockquote>
|
|
|
|
<p>
|
|
The reason this doesn't compile is because operator== was implemented
|
|
as a member function of the nested classes set:iterator and
|
|
set::const_iterator, and there is no conversion from const_iterator to
|
|
iterator. Surprisingly, (s.end() == i) does work, though, because of
|
|
the conversion from iterator to const_iterator.
|
|
</p>
|
|
|
|
<p>
|
|
I don't see a requirement anywhere in the standard that this must
|
|
work. Should there be one? If so, I think the requirement would need
|
|
to be added to the tables in section 24.1.1. I'm not sure about the
|
|
wording. If this requirement existed in the standard, I would think
|
|
that implementors would have to make the comparison operators
|
|
non-member functions.</p>
|
|
|
|
<p>This issues was also raised on comp.std.c++ by Darin
|
|
Adler. The example given was:</p>
|
|
|
|
<blockquote>
|
|
<pre>bool check_equal(std::deque<int>::iterator i,
|
|
std::deque<int>::const_iterator ci)
|
|
{
|
|
return i == ci;
|
|
}</pre>
|
|
</blockquote>
|
|
|
|
<p>Comment from John Potter:</p>
|
|
<blockquote>
|
|
<p>
|
|
In case nobody has noticed, accepting it will break reverse_iterator.
|
|
</p>
|
|
|
|
<p>
|
|
The fix is to make the comparison operators templated on two types.
|
|
</p>
|
|
|
|
<pre>
|
|
template <class Iterator1, class Iterator2>
|
|
bool operator== (reverse_iterator<Iterator1> const& x,
|
|
reverse_iterator<Iterator2> const& y);
|
|
</pre>
|
|
|
|
<p>
|
|
Obviously: return x.base() == y.base();
|
|
</p>
|
|
|
|
<p>
|
|
Currently, no reverse_iterator to const_reverse_iterator compares are
|
|
valid.
|
|
</p>
|
|
|
|
<p>
|
|
BTW, I think the issue is in support of bad code. Compares should be
|
|
between two iterators of the same type. All std::algorithms require
|
|
the begin and end iterators to be of the same type.
|
|
</p>
|
|
</blockquote>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Insert this paragraph after 23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a> paragraph 7:</p>
|
|
<blockquote>
|
|
<p>In the expressions</p>
|
|
<pre>
|
|
i == j
|
|
i != j
|
|
i < j
|
|
i <= j
|
|
i >= j
|
|
i > j
|
|
i - j
|
|
</pre>
|
|
<p>Where i and j denote objects of a container's iterator type,
|
|
either or both may be replaced by an object of the container's
|
|
const_iterator type referring to the same element with no
|
|
change in semantics.</p>
|
|
</blockquote>
|
|
|
|
<p><i>[post-Toronto: Judy supplied a proposed resolution saying that
|
|
<tt>iterator</tt> and <tt>const_iterator</tt> could be freely mixed in
|
|
iterator comparison and difference operations.]</i></p>
|
|
|
|
<p><i>[Redmond: Dave and Howard supplied a new proposed resolution which
|
|
explicitly listed expressions; there was concern that the previous
|
|
proposed resolution was too informal.]</i></p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
The LWG believes it is clear that the above wording applies only to
|
|
the nested types <tt>X::iterator</tt> and <tt>X::const_iterator</tt>,
|
|
where <tt>X</tt> is a container. There is no requirement that
|
|
<tt>X::reverse_iterator</tt> and <tt>X::const_reverse_iterator</tt>
|
|
can be mixed. If mixing them is considered important, that's a
|
|
separate issue. (Issue <a href="lwg-active.html#280">280</a>.)
|
|
</p>
|
|
<hr>
|
|
<a name="187"><h3>187. iter_swap underspecified</h3></a><p>
|
|
<b>Section:</b> 25.2.2 <a href="lib-algorithms.html#lib.alg.swap"> [lib.alg.swap]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Andrew Koenig <b>Date:</b> 14 Aug 1999</p>
|
|
<p>The description of iter_swap in 25.2.2 paragraph 7,says that it ``exchanges the values''
|
|
of the objects to which two iterators refer.<br>
|
|
<br>
|
|
What it doesn't say is whether it does so using swap or using the assignment operator and copy constructor.<br>
|
|
<br>
|
|
This question is an important one to answer, because swap is specialized to work efficiently for standard containers.<br>
|
|
For example:</p>
|
|
<blockquote>
|
|
<pre>vector<int> v1, v2;
|
|
iter_swap(&v1, &v2);</pre>
|
|
</blockquote>
|
|
<p>Is this call to iter_swap equivalent to calling swap(v1, v2)? Or is it equivalent to</p>
|
|
<blockquote>
|
|
<pre>{
|
|
vector<int> temp = v1;
|
|
v1 = v2;
|
|
v2 = temp;
|
|
}</pre>
|
|
</blockquote>
|
|
<p>The first alternative is O(1); the second is O(n).</p>
|
|
<p>A LWG member, Dave Abrahams, comments:</p>
|
|
<blockquote>
|
|
<p>Not an objection necessarily, but I want to point out the cost of that requirement:</p>
|
|
<blockquote>
|
|
<p><tt>iter_swap(list<T>::iterator, list<T>::iterator)</tt></p>
|
|
</blockquote>
|
|
<p>can currently be specialized to be more efficient than iter_swap(T*,T*) for many T (by using splicing). Your proposal would make that optimization
|
|
illegal. </p>
|
|
</blockquote>
|
|
|
|
<p><i>[Kona: The LWG notes the original need for iter_swap was proxy iterators
|
|
which are no longer permitted.]</i></p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the effect clause of iter_swap in 25.2.2 paragraph 7 from:</p>
|
|
<blockquote>
|
|
<p>Exchanges the values pointed to by the two iterators a and b.</p>
|
|
</blockquote>
|
|
<p>to</p>
|
|
<blockquote>
|
|
<p>
|
|
<tt>swap(*a, *b)</tt>.</p>
|
|
</blockquote>
|
|
|
|
<p><i>[post-Toronto: The LWG is concerned about possible
|
|
overspecification: there may be cases, such as Dave Abrahams's example
|
|
above, and such as vector<bool>'s iterators, where it makes more
|
|
sense for iter_swap to do something other than swap. If performance
|
|
is a concern, it may be better to have explicit complexity
|
|
requirements than to say how iter_swap should be implemented.]</i></p>
|
|
|
|
<p><i>[Redmond: Discussed, with no consensus. There was very little
|
|
support for the proposed resolution. Some people favored closing this
|
|
issue as NAD. Others favored a more complicated specification of
|
|
<tt>iter_swap</tt>, which might distinguish between ordinary iterators
|
|
and proxies. A possible new issue: how do we know that the iterators
|
|
passed to <tt>iter_swap</tt> have Assignable value types? (If this
|
|
new issue is real, it extends far beyond just
|
|
<tt>iter_swap</tt>.)]</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="200"><h3>200. Forward iterator requirements don't allow constant 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#Ready">Ready</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 19 Nov 1999</p>
|
|
<p>
|
|
In table 74, the return type of the expression <tt>*a</tt> is given
|
|
as <tt>T&</tt>, where <tt>T</tt> is the iterator's value type.
|
|
For constant iterators, however, this is wrong. ("Value type"
|
|
is never defined very precisely, but it is clear that the value type
|
|
of, say, <tt>std::list<int>::const_iterator</tt> is supposed to be
|
|
<tt>int</tt>, not <tt>const int</tt>.)
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In table 74, in the <tt>*a</tt> and <tt>*r++</tt> rows, change the
|
|
return type from "<tt>T&</tt>" to "<tt>T&</tt>
|
|
if <tt>X</tt> is mutable, otherwise <tt>const T&</tt>".
|
|
In the <tt>a->m</tt> row, change the return type from
|
|
"<tt>U&</tt>" to "<tt>U&</tt> if <tt>X</tt> is mutable,
|
|
otherwise <tt>const U&</tt>".
|
|
</p>
|
|
|
|
<p><i>[Tokyo: The LWG believes this is the tip of a larger iceberg;
|
|
there are multiple const problems with the STL portion of the library
|
|
and that these should be addressed as a single package. Note
|
|
that issue <a href="lwg-closed.html#180">180</a> has already been declared NAD Future for
|
|
that very reason.]</i></p>
|
|
|
|
<p><i>[Redmond: the LWG thinks this is separable from other constness
|
|
issues. This issue is just cleanup; it clarifies language that was
|
|
written before we had iterator_traits. Proposed resolution was
|
|
modified: the original version only discussed *a. It was pointed out
|
|
that we also need to worry about *r++ and a->m.]</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="202"><h3>202. unique() effects unclear when predicate not an equivalence relation</h3></a><p>
|
|
<b>Section:</b> 25.2.8 <a href="lib-algorithms.html#lib.alg.unique"> [lib.alg.unique]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Andrew Koenig <b>Date:</b> 13 Jan 2000</p>
|
|
<p>
|
|
What should unique() do if you give it a predicate that is not an
|
|
equivalence relation? There are at least two plausible answers:
|
|
</p>
|
|
|
|
<blockquote>
|
|
|
|
<p>
|
|
1. You can't, because 25.2.8 says that it it "eliminates all but
|
|
the first element from every consecutive group of equal
|
|
elements..." and it wouldn't make sense to interpret "equal" as
|
|
meaning anything but an equivalence relation. [It also doesn't
|
|
make sense to interpret "equal" as meaning ==, because then there
|
|
would never be any sense in giving a predicate as an argument at
|
|
all.]
|
|
</p>
|
|
|
|
<p>
|
|
2. The word "equal" should be interpreted to mean whatever the
|
|
predicate says, even if it is not an equivalence relation
|
|
(and in particular, even if it is not transitive).
|
|
</p>
|
|
|
|
</blockquote>
|
|
|
|
<p>
|
|
The example that raised this question is from Usenet:
|
|
</p>
|
|
|
|
<blockquote>
|
|
|
|
<pre>int f[] = { 1, 3, 7, 1, 2 };
|
|
int* z = unique(f, f+5, greater<int>());</pre>
|
|
|
|
</blockquote>
|
|
|
|
<p>
|
|
If one blindly applies the definition using the predicate
|
|
greater<int>, and ignore the word "equal", you get:
|
|
</p>
|
|
|
|
<blockquote>
|
|
|
|
<p>
|
|
Eliminates all but the first element from every consecutive group
|
|
of elements referred to by the iterator i in the range [first, last)
|
|
for which *i > *(i - 1).
|
|
</p>
|
|
|
|
</blockquote>
|
|
|
|
<p>
|
|
The first surprise is the order of the comparison. If we wanted to
|
|
allow for the predicate not being an equivalence relation, then we
|
|
should surely compare elements the other way: pred(*(i - 1), *i). If
|
|
we do that, then the description would seem to say: "Break the
|
|
sequence into subsequences whose elements are in strictly increasing
|
|
order, and keep only the first element of each subsequence". So the
|
|
result would be 1, 1, 2. If we take the description at its word, it
|
|
would seem to call for strictly DEcreasing order, in which case the
|
|
result should be 1, 3, 7, 2.<br>
|
|
<br>
|
|
In fact, the SGI implementation of unique() does neither: It yields 1,
|
|
3, 7.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 25.2.8 <a href="lib-algorithms.html#lib.alg.unique"> [lib.alg.unique]</a> paragraph 1 to:</p>
|
|
<blockquote>
|
|
For a nonempty range, eliminates all but the first element from every
|
|
consecutive group of equivalent elements referred to by the iterator
|
|
<tt>i</tt> in the range [first+1, last) for which the following
|
|
conditions hold: <tt>*(i-1) == *i</tt> or <tt>pred(*(i-1), *i) !=
|
|
false</tt>.
|
|
</blockquote>
|
|
|
|
<p>
|
|
Also insert a new paragraph, paragraph 2a, that reads: "Requires: The
|
|
comparison function must be an equivalence relation."
|
|
</p>
|
|
|
|
<p><i>[Redmond: discussed arguments for and against requiring the
|
|
comparison function to be an equivalence relation. Straw poll:
|
|
14-2-5. First number is to require that it be an equivalence
|
|
relation, second number is to explicitly not require that it be an
|
|
equivalence relation, third number is people who believe they need
|
|
more time to consider the issue. A separate issue: Andy Sawyer
|
|
pointed out that "i-1" is incorrect, since "i" can refer to the first
|
|
iterator in the range. Matt provided wording to address this
|
|
problem.]</i></p>
|
|
|
|
<p><i>[Curaçao: The LWG changed "... the range (first,
|
|
last)..." to "... the range [first+1, last)..." for
|
|
clarity. They considered this change close enough to editorial to not
|
|
require another round of review.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>The LWG also considered an alternative resolution: change
|
|
25.2.8 <a href="lib-algorithms.html#lib.alg.unique"> [lib.alg.unique]</a> paragraph 1 to:</p>
|
|
|
|
<blockquote>
|
|
For a nonempty range, eliminates all but the first element from every
|
|
consecutive group of elements referred to by the iterator
|
|
<tt>i</tt> in the range (first, last) for which the following
|
|
conditions hold: <tt>*(i-1) == *i</tt> or <tt>pred(*(i-1), *i) !=
|
|
false</tt>.
|
|
</blockquote>
|
|
|
|
<p>
|
|
Also insert a new paragraph, paragraph 1a, that reads: "Notes: The
|
|
comparison function need not be an equivalence relation."
|
|
</p>
|
|
|
|
|
|
<p>Informally: the proposed resolution imposes an explicit requirement
|
|
that the comparison function be an equivalence relation. The
|
|
alternative resolution does not, and it gives enough information so
|
|
that the behavior of unique() for a non-equivalence relation is
|
|
specified. Both resolutions are consistent with the behavior of
|
|
existing implementations.</p>
|
|
<hr>
|
|
<a name="225"><h3>225. std:: algorithms use of other unqualified algorithms</h3></a><p>
|
|
<b>Section:</b> 17.4.4.3 <a href="lib-intro.html#lib.global.functions"> [lib.global.functions]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 01 Apr 2000</p>
|
|
<p>Are algorithms in std:: allowed to use other algorithms without qualification, so functions in
|
|
user namespaces might be found through Koenig lookup?</p>
|
|
<p>For example, a popular standard library implementation includes this
|
|
implementation of std::unique:</p>
|
|
<blockquote>
|
|
<pre>namespace std {
|
|
template <class _ForwardIter>
|
|
_ForwardIter unique(_ForwardIter __first, _ForwardIter __last) {
|
|
__first = adjacent_find(__first, __last);
|
|
return unique_copy(__first, __last, __first);
|
|
}
|
|
}</pre>
|
|
</blockquote>
|
|
<p>Imagine two users on opposite sides of town, each using unique on his own
|
|
sequences bounded by my_iterators . User1 looks at his standard library
|
|
implementation and says, "I know how to implement a more efficient
|
|
unique_copy for my_iterators", and writes:</p>
|
|
<blockquote>
|
|
<pre>namespace user1 {
|
|
class my_iterator;
|
|
// faster version for my_iterator
|
|
my_iterator unique_copy(my_iterator, my_iterator, my_iterator);
|
|
}</pre>
|
|
</blockquote>
|
|
<p>user1::unique_copy() is selected by Koenig lookup, as he intended.</p>
|
|
<p>User2 has other needs, and writes:</p>
|
|
<blockquote>
|
|
<pre>namespace user2 {
|
|
class my_iterator;
|
|
// Returns true iff *c is a unique copy of *a and *b.
|
|
bool unique_copy(my_iterator a, my_iterator b, my_iterator c);
|
|
}</pre>
|
|
</blockquote>
|
|
<p>User2 is shocked to find later that his fully-qualified use of
|
|
std::unique(user2::my_iterator, user2::my_iterator, user2::my_iterator) fails to
|
|
compile (if he's lucky). Looking in the standard, he sees the following Effects
|
|
clause for unique():</p>
|
|
<blockquote>
|
|
<p>Effects: Eliminates all but the first element from every consecutive group
|
|
of equal elements referred to by the iterator i in the range [first, last) for
|
|
which the following corresponding conditions hold: *i == *(i - 1) or pred(*i,
|
|
*(i - 1)) != false</p>
|
|
</blockquote>
|
|
<p>The standard gives user2 absolutely no reason to think he can interfere with
|
|
std::unique by defining names in namespace user2. His standard library has been
|
|
built with the template export feature, so he is unable to inspect the
|
|
implementation. User1 eventually compiles his code with another compiler, and
|
|
his version of unique_copy silently stops being called. Eventually, he realizes
|
|
that he was depending on an implementation detail of his library and had no
|
|
right to expect his unique_copy() to be called portably.</p>
|
|
<p>On the face of it, and given above scenario, it may seem obvious that the
|
|
implementation of unique() shown is non-conforming because it uses unique_copy()
|
|
rather than ::std::unique_copy(). Most standard library implementations,
|
|
however, seem to disagree with this notion.</p>
|
|
<p> <i>[Tokyo: Steve Adamczyk from
|
|
the core working group indicates that "std::" is sufficient;
|
|
leading "::" qualification is not required because any namespace
|
|
qualification is sufficient to suppress Koenig lookup.]</i>
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Add a paragraph and a note at the end of
|
|
17.4.4.3 <a href="lib-intro.html#lib.global.functions"> [lib.global.functions]</a>:</p>
|
|
<blockquote>
|
|
|
|
<p>Unless otherwise specified, no global or non-member function in the
|
|
standard library shall use a function from another namespace which is
|
|
found through <i>argument-dependent name lookup</i> (3.4.2 <a href="basic.html#basic.lookup.koenig"> [basic.lookup.koenig]</a>).</p>
|
|
|
|
<p>[Note: the phrase "unless otherwise specified" is intended to
|
|
allow Koenig lookup in cases like that of ostream_iterators:<br>
|
|
|
|
<br>
|
|
Effects:</p>
|
|
<blockquote>
|
|
<p>*out_stream << value;<br>
|
|
if(delim != 0) *out_stream << delim;<br>
|
|
return (*this);</p>
|
|
<p>--end note]</p>
|
|
</blockquote>
|
|
</blockquote>
|
|
|
|
<p><i>[Tokyo: The LWG agrees that this is a defect in the standard, but
|
|
is as yet unsure if the proposed resolution is the best
|
|
solution. Furthermore, the LWG believes that the same problem of
|
|
unqualified library names applies to wording in the standard itself,
|
|
and has opened issue <a href="lwg-active.html#229">229</a> accordingly. Any resolution of
|
|
issue <a href="lwg-active.html#225">225</a> should be coordinated with the resolution of
|
|
issue <a href="lwg-active.html#229">229</a>.]</i></p>
|
|
|
|
<p><i>[Toronto: The LWG is not sure if this is a defect in the
|
|
standard. Most LWG members believe that an implementation of
|
|
<tt>std::unique</tt> like the one quoted in this issue is already
|
|
illegal, since, under certain circumstances, its semantics are not
|
|
those specified in the standard. The standard's description of
|
|
<tt>unique</tt> does not say that overloading <tt>adjacent_find</tt>
|
|
should have any effect.]</i></p>
|
|
|
|
<p><i>[Curaçao: An LWG-subgroup spent an afternoon working on issues
|
|
225, 226, and 229. Their conclusion was that the issues should be
|
|
separated into an LWG portion (Howard's paper, N1387=02-0045), and a
|
|
EWG portion (Dave will write a proposal). The LWG and EWG had
|
|
(separate) discussions of this plan the next day. The proposed
|
|
resolution for this issue is in accordance with Howard's paper.]</i></p>
|
|
|
|
<hr>
|
|
<a name="226"><h3>226. User supplied specializations or overloads of namespace std function 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#Review">Review</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 01 Apr 2000</p>
|
|
<p>The issues are: </p>
|
|
<p>1. How can a 3rd party library implementor (lib1) write a version of a standard
|
|
algorithm which is specialized to work with his own class template? </p>
|
|
<p>2. How can another library implementor (lib2) write a generic algorithm which
|
|
will take advantage of the specialized algorithm in lib1?</p>
|
|
<p>This appears to be the only viable answer under current language rules:</p>
|
|
<blockquote>
|
|
<pre>namespace lib1
|
|
{
|
|
// arbitrary-precision numbers using T as a basic unit
|
|
template <class T>
|
|
class big_num { //...
|
|
};
|
|
</pre>
|
|
<pre> // defining this in namespace std is illegal (it would be an
|
|
// overload), so we hope users will rely on Koenig lookup
|
|
template <class T>
|
|
void swap(big_int<T>&, big_int<T>&);
|
|
}</pre>
|
|
<pre>#include <algorithm>
|
|
namespace lib2
|
|
{
|
|
template <class T>
|
|
void generic_sort(T* start, T* end)
|
|
{
|
|
...
|
|
// using-declaration required so we can work on built-in types
|
|
using std::swap;
|
|
// use Koenig lookup to find specialized algorithm if available
|
|
swap(*x, *y);
|
|
}
|
|
}</pre>
|
|
</blockquote>
|
|
<p>This answer has some drawbacks. First of all, it makes writing lib2 difficult
|
|
and somewhat slippery. The implementor needs to remember to write the
|
|
using-declaration, or generic_sort will fail to compile when T is a built-in
|
|
type. The second drawback is that the use of this style in lib2 effectively
|
|
"reserves" names in any namespace which defines types which may
|
|
eventually be used with lib2. This may seem innocuous at first when applied to
|
|
names like swap, but consider more ambiguous names like unique_copy() instead.
|
|
It is easy to imagine the user wanting to define these names differently in his
|
|
own namespace. A definition with semantics incompatible with the standard
|
|
library could cause serious problems (see issue <a href="lwg-active.html#225">225</a>).</p>
|
|
<p>Why, you may ask, can't we just partially specialize std::swap()? It's
|
|
because the language doesn't allow for partial specialization of function
|
|
templates. If you write:</p>
|
|
<blockquote>
|
|
<pre>namespace std
|
|
{
|
|
template <class T>
|
|
void swap(lib1::big_int<T>&, lib1::big_int<T>&);
|
|
}</pre>
|
|
</blockquote>
|
|
<p>You have just overloaded std::swap, which is illegal under the current
|
|
language rules. On the other hand, the following full specialization is legal:</p>
|
|
<blockquote>
|
|
<pre>namespace std
|
|
{
|
|
template <>
|
|
void swap(lib1::other_type&, lib1::other_type&);
|
|
}</pre>
|
|
</blockquote>
|
|
|
|
<p>This issue reflects concerns raised by the "Namespace issue
|
|
with specialized swap" thread on comp.lang.c++.moderated. A
|
|
similar set of concerns was earlier raised on the boost.org mailing
|
|
list and the ACCU-general mailing list. Also see library reflector
|
|
message c++std-lib-7354.</p>
|
|
|
|
<p>
|
|
J. C. van Winkel points out (in c++std-lib-9565) another unexpected
|
|
fact: it's impossible to output a container of std::pair's using copy
|
|
and an ostream_iterator, as long as both pair-members are built-in or
|
|
std:: types. That's because a user-defined operator<< for (for
|
|
example) std::pair<const std::string, int> will not be found:
|
|
lookup for operator<< will be performed only in namespace std.
|
|
Opinions differed on whether or not this was a defect, and, if so,
|
|
whether the defect is that something is wrong with user-defined
|
|
functionality and std, or whether it's that the standard library does
|
|
not provide an operator<< for std::pair<>.
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>Adopt the wording in the <b>Customization Points</b> section of
|
|
Howard Hinnant's paper, N1387=02-0045.</p>
|
|
|
|
<p><i>[Tokyo: Summary, "There is no conforming way to extend
|
|
std::swap for user defined templates." The LWG agrees that
|
|
there is a problem. Would like more information before
|
|
proceeding. This may be a core issue. Core issue 229 has been opened
|
|
to discuss the core aspects of this problem. It was also noted that
|
|
submissions regarding this issue have been received from several
|
|
sources, but too late to be integrated into the issues list.
|
|
]</i></p>
|
|
|
|
<p><i>[Post-Tokyo: A paper with several proposed resolutions,
|
|
J16/00-0029==WG21/N1252, "Shades of namespace std functions
|
|
" by Alan Griffiths, is in the Post-Tokyo mailing. It
|
|
should be considered a part of this issue.]</i></p>
|
|
|
|
<p><i>[Toronto: Dave Abrahams and Peter Dimov have proposed a
|
|
resolution that involves core changes: it would add partial
|
|
specialization of function template. The Core Working Group is
|
|
reluctant to add partial specialization of function templates. It is
|
|
viewed as a large change, CWG believes that proposal presented leaves
|
|
some syntactic issues unanswered; if the CWG does add partial
|
|
specialization of function templates, it wishes to develop its own
|
|
proposal. The LWG continues to believe that there is a serious
|
|
problem: there is no good way for users to force the library to use
|
|
user specializations of generic standard library functions, and in
|
|
certain cases (e.g. transcendental functions called by
|
|
<tt>valarray</tt> and <tt>complex</tt>) this is important. Koenig
|
|
lookup isn't adequate, since names within the library must be
|
|
qualified with <tt>std</tt> (see issue 225), specialization doesn't
|
|
work (we don't have partial specialization of function templates), and
|
|
users aren't permitted to add overloads within namespace std.
|
|
]</i></p>
|
|
|
|
<p><i>[Copenhagen: Discussed at length, with no consensus. Relevant
|
|
papers in the pre-Copenhagen mailing: N1289, N1295, N1296. Discussion
|
|
focused on four options. (1) Relax restrictions on overloads within
|
|
namespace std. (2) Mandate that the standard library use unqualified
|
|
calls for <tt>swap</tt> and possibly other functions. (3) Introduce
|
|
helper class templates for <tt>swap</tt> and possibly other functions.
|
|
(4) Introduce partial specialization of function templates. Every
|
|
option had both support and opposition. Straw poll (first number is
|
|
support, second is strongly opposed): (1) 6, 4; (2) 6, 7; (3) 3, 8;
|
|
(4) 4, 4.]</i></p>
|
|
|
|
<p><i>[Redmond: Discussed, again no consensus. Herb presented an
|
|
argument that a user who is defining a type <tt>T</tt> with an
|
|
associated <tt>swap</tt> should not be expected to put that
|
|
<tt>swap</tt> in namespace std, either by overloading or by partial
|
|
specialization. The argument is that <tt>swap</tt> is part of
|
|
<tt>T</tt>'s interface, and thus should to in the same namespace as
|
|
<tt>T</tt> and only in that namespace. If we accept this argument,
|
|
the consequence is that standard library functions should use
|
|
unqualified call of <tt>swap</tt>. (And which other functions? Any?)
|
|
A small group (Nathan, Howard, Jeremy, Dave, Matt, Walter, Marc) will
|
|
try to put together a proposal before the next meeting.]</i></p>
|
|
|
|
<p><i>[Curaçao: An LWG-subgroup spent an afternoon working on issues
|
|
225, 226, and 229. Their conclusion was that the issues should be
|
|
separated into an LWG portion (Howard's paper, N1387=02-0045), and a
|
|
EWG portion (Dave will write a proposal). The LWG and EWG had
|
|
(separate) discussions of this plan the next day. The proposed
|
|
resolution is the one proposed by Howard.]</i></p>
|
|
|
|
<hr>
|
|
<a name="229"><h3>229. Unqualified references of other library entities</h3></a><p>
|
|
<b>Section:</b> 17.4.1.1 <a href="lib-intro.html#lib.contents"> [lib.contents]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> Steve Clamage <b>Date:</b> 19 Apr 2000</p>
|
|
<p>Throughout the library chapters, the descriptions of library entities refer
|
|
to other library entities without necessarily qualifying the names.</p>
|
|
|
|
<p>For example, section 25.2.2 "Swap" describes the effect of
|
|
swap_ranges in terms of the unqualified name "swap". This section
|
|
could reasonably be interpreted to mean that the library must be implemented so
|
|
as to do a lookup of the unqualified name "swap", allowing users to
|
|
override any ::std::swap function when Koenig lookup applies.</p>
|
|
|
|
<p>Although it would have been best to use explicit qualification with
|
|
"::std::" throughout, too many lines in the standard would have to be
|
|
adjusted to make that change in a Technical Corrigendum.</p>
|
|
|
|
<p>Issue <a href="lwg-defects.html#182">182</a>, which addresses qualification of
|
|
<tt>size_t</tt>, is a special case of this.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>To section 17.4.1.1 "Library contents" Add the following paragraph:</p>
|
|
<blockquote>
|
|
<p>Whenever a name x defined in the standard library is mentioned, the name x
|
|
is assumed to be fully qualified as ::std::x, unless explicitly described
|
|
otherwise. For example, if the Effects section for library function F is
|
|
described as calling library function G, the function ::std::G is meant.</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Post-Tokyo: Steve Clamage submitted this issue at the request of
|
|
the LWG to solve a problem in the standard itself similar to the
|
|
problem within implementations of library identified by issue <a href="lwg-active.html#225">225</a>. Any resolution of issue <a href="lwg-active.html#225">225</a> should be
|
|
coordinated with the resolution of this issue.]</i></p>
|
|
|
|
<p><i>[post-Toronto: Howard is undecided about whether it is
|
|
appropriate for all standard library function names referred to in
|
|
other standard library functions to be explicitly qualified by
|
|
<tt>std</tt>: it is common advice that users should define global
|
|
functions that operate on their class in the same namespace as the
|
|
class, and this requires argument-dependent lookup if those functions
|
|
are intended to be called by library code. Several LWG members are
|
|
concerned that valarray appears to require argument-dependent lookup,
|
|
but that the wording may not be clear enough to fall under
|
|
"unless explicitly described otherwise".]</i></p>
|
|
|
|
<p><i>[Curaçao: An LWG-subgroup spent an afternoon working on issues
|
|
225, 226, and 229. Their conclusion was that the issues should be
|
|
separated into an LWG portion (Howard's paper, N1387=02-0045), and a
|
|
EWG portion (Dave will write a proposal). The LWG and EWG had
|
|
(separate) discussions of this plan the next day. This paper resolves
|
|
issues 225 and 226. In light of that resolution, the proposed
|
|
resolution for the current issue makes sense.]</i></p>
|
|
|
|
<hr>
|
|
<a name="231"><h3>231. Precision in iostream?</h3></a><p>
|
|
<b>Section:</b> 22.2.2.2.2 <a href="lib-locales.html#lib.facet.num.put.virtuals"> [lib.facet.num.put.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> James Kanze, Stephen Clamage <b>Date:</b> 25 Apr 2000</p>
|
|
<p>What is the following program supposed to output?</p>
|
|
<pre>#include <iostream>
|
|
|
|
int
|
|
main()
|
|
{
|
|
std::cout.setf( std::ios::scientific , std::ios::floatfield ) ;
|
|
std::cout.precision( 0 ) ;
|
|
std::cout << 1.00 << '\n' ;
|
|
return 0 ;
|
|
}</pre>
|
|
<p>From my C experience, I would expect "1e+00"; this is what
|
|
<tt>printf("%.0e" , 1.00 );</tt> does. G++ outputs
|
|
"1.000000e+00".</p>
|
|
|
|
<p>The only indication I can find in the standard is 22.2.2.2.2/11,
|
|
where it says "For conversion from a floating-point type, if
|
|
(flags & fixed) != 0 or if str.precision() > 0, then
|
|
str.precision() is specified in the conversion specification."
|
|
This is an obvious error, however, fixed is not a mask for a field,
|
|
but a value that a multi-bit field may take -- the results of and'ing
|
|
fmtflags with ios::fixed are not defined, at least not if
|
|
ios::scientific has been set. G++'s behavior corresponds to what might
|
|
happen if you do use (flags & fixed) != 0 with a typical
|
|
implementation (floatfield == 3 << something, fixed == 1
|
|
<< something, and scientific == 2 << something).</p>
|
|
|
|
<p>Presumably, the intent is either (flags & floatfield) != 0, or
|
|
(flags & floatfield) == fixed; the first gives something more or
|
|
less like the effect of precision in a printf floating point
|
|
conversion. Only more or less, of course. In order to implement printf
|
|
formatting correctly, you must know whether the precision was
|
|
explicitly set or not. Say by initializing it to -1, instead of 6, and
|
|
stating that for floating point conversions, if precision < -1, 6
|
|
will be used, for fixed point, if precision < -1, 1 will be used,
|
|
etc. Plus, of course, if precision == 0 and flags & floatfield ==
|
|
0, 1 should be = used. But it probably isn't necessary to emulate all
|
|
of the anomalies of printf:-).</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Replace 22.2.2.2.2 <a href="lib-locales.html#lib.facet.num.put.virtuals"> [lib.facet.num.put.virtuals]</a>, paragraph 11, with the following
|
|
sentence:
|
|
</p>
|
|
<blockquote>
|
|
For conversion from a floating-point type,
|
|
<tt><i>str</i>.precision()</tt> is specified in the conversion
|
|
specification.
|
|
</blockquote>
|
|
<p><b>Rationale:</b></p>
|
|
<p>The floatfield determines whether numbers are formatted as if
|
|
with %f, %e, or %g. If the <tt>fixed</tt> bit is set, it's %f,
|
|
if <tt>scientific</tt> it's %e, and if both bits are set, or
|
|
neither, it's %g.</p>
|
|
<p>Turning to the C standard, a precision of 0 is meaningful
|
|
for %f and %e. For %g, precision 0 is taken to be the same as
|
|
precision 1.</p>
|
|
<p>The proposed resolution has the effect that if neither
|
|
<tt>fixed</tt> nor <tt>scientific</tt> is set we'll be
|
|
specifying a precision of 0, which will be internally
|
|
turned into 1. There's no need to call it out as a special
|
|
case.</p>
|
|
<p>The output of the above program will be "1e+00".</p>
|
|
|
|
<p><i>[Post-Curaçao: Howard provided improved wording covering the case
|
|
where precision is 0 and mode is %g.]</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="241"><h3>241. Does unique_copy() require CopyConstructible and Assignable?</h3></a><p>
|
|
<b>Section:</b> 25.2.8 <a href="lib-algorithms.html#lib.alg.unique"> [lib.alg.unique]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Angelika Langer <b>Date:</b> May 15 2000</p>
|
|
|
|
<p>Some popular implementations of unique_copy() create temporary
|
|
copies of values in the input sequence, at least if the input iterator
|
|
is a pointer. Such an implementation is built on the assumption that
|
|
the value type is CopyConstructible and Assignable.</p>
|
|
|
|
<p>It is common practice in the standard that algorithms explicitly
|
|
specify any additional requirements that they impose on any of the
|
|
types used by the algorithm. An example of an algorithm that creates
|
|
temporary copies and correctly specifies the additional requirements
|
|
is accumulate(), 26.4.1 <a href="lib-numerics.html#lib.accumulate"> [lib.accumulate]</a>.</p>
|
|
|
|
<p>Since the specifications of unique() and unique_copy() do not
|
|
require CopyConstructible and Assignable of the InputIterator's value
|
|
type the above mentioned implementations are not standard-compliant. I
|
|
cannot judge whether this is a defect in the standard or a defect in
|
|
the implementations.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 25.2.8 change:</p>
|
|
|
|
<blockquote>
|
|
-4- Requires: The ranges [first, last) and [result, result+(last-first))
|
|
shall not overlap.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>-4- Requires: The ranges [first, last) and [result,
|
|
result+(last-first)) shall not overlap. The expression *result =
|
|
*first must be valid. If neither InputIterator nor OutputIterator
|
|
meets the requirements of forward iterator then the value type of
|
|
InputIterator must be copy constructible. Otherwise copy
|
|
constructible is not required. </p>
|
|
</blockquote>
|
|
|
|
<p><i>[Redmond: the original proposed resolution didn't impose an
|
|
explicit requirement that the iterator's value type must be copy
|
|
constructible, on the grounds that an input iterator's value type must
|
|
always be copy constructible. Not everyone in the LWG thought that
|
|
this requirement was clear from table 72. It has been suggested that
|
|
it might be possible to implement <tt>unique_copy</tt> without
|
|
requiring assignability, although current implementations do impose
|
|
that requirement. Howard provided new wording.]</i></p>
|
|
|
|
<p><i>[
|
|
Curaçao: The LWG changed the PR editorially to specify
|
|
"neither...nor...meet..." as clearer than
|
|
"both...and...do not meet...". Change believed to be so
|
|
minor as not to require re-review.
|
|
]</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="253"><h3>253. valarray helper functions are almost entirely useless</h3></a><p>
|
|
<b>Section:</b> 26.3.2.1 <a href="lib-numerics.html#lib.valarray.cons"> [lib.valarray.cons]</a>, 26.3.2.2 <a href="lib-numerics.html#lib.valarray.assign"> [lib.valarray.assign]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Robert Klarer <b>Date:</b> 31 Jul 2000</p>
|
|
<p>This discussion is adapted from message c++std-lib-7056 posted
|
|
November 11, 1999. I don't think that anyone can reasonably claim
|
|
that the problem described below is NAD.</p>
|
|
|
|
<p>These valarray constructors can never be called:</p>
|
|
|
|
<pre>
|
|
template <class T>
|
|
valarray<T>::valarray(const slice_array<T> &);
|
|
template <class T>
|
|
valarray<T>::valarray(const gslice_array<T> &);
|
|
template <class T>
|
|
valarray<T>::valarray(const mask_array<T> &);
|
|
template <class T>
|
|
valarray<T>::valarray(const indirect_array<T> &);
|
|
</pre>
|
|
|
|
<p>Similarly, these valarray assignment operators cannot be
|
|
called:</p>
|
|
|
|
<pre>
|
|
template <class T>
|
|
valarray<T> valarray<T>::operator=(const slice_array<T> &);
|
|
template <class T>
|
|
valarray<T> valarray<T>::operator=(const gslice_array<T> &);
|
|
template <class T>
|
|
valarray<T> valarray<T>::operator=(const mask_array<T> &);
|
|
template <class T>
|
|
valarray<T> valarray<T>::operator=(const indirect_array<T> &);
|
|
</pre>
|
|
|
|
<p>Please consider the following example:</p>
|
|
|
|
<pre>
|
|
#include <valarray>
|
|
using namespace std;
|
|
|
|
int main()
|
|
{
|
|
valarray<double> va1(12);
|
|
valarray<double> va2(va1[slice(1,4,3)]); // line 1
|
|
}
|
|
</pre>
|
|
|
|
|
|
<p>Since the valarray va1 is non-const, the result of the sub-expression
|
|
va1[slice(1,4,3)] at line 1 is an rvalue of type const
|
|
std::slice_array<double>. This slice_array rvalue is then used to
|
|
construct va2. The constructor that is used to construct va2 is
|
|
declared like this:</p>
|
|
|
|
<pre>
|
|
template <class T>
|
|
valarray<T>::valarray(const slice_array<T> &);
|
|
</pre>
|
|
|
|
<p>Notice the constructor's const reference parameter. When the
|
|
constructor is called, a slice_array must be bound to this reference.
|
|
The rules for binding an rvalue to a const reference are in 8.5.3,
|
|
paragraph 5 (see also 13.3.3.1.4). Specifically, paragraph 5
|
|
indicates that a second slice_array rvalue is constructed (in this
|
|
case copy-constructed) from the first one; it is this second rvalue
|
|
that is bound to the reference parameter. Paragraph 5 also requires
|
|
that the constructor that is used for this purpose be callable,
|
|
regardless of whether the second rvalue is elided. The
|
|
copy-constructor in this case is not callable, however, because it is
|
|
private. Therefore, the compiler should report an error.</p>
|
|
|
|
<p>Since slice_arrays are always rvalues, the valarray constructor that has a
|
|
parameter of type const slice_array<T> & can never be called. The
|
|
same reasoning applies to the three other constructors and the four
|
|
assignment operators that are listed at the beginning of this post.
|
|
Furthermore, since these functions cannot be called, the valarray helper
|
|
classes are almost entirely useless.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>slice_array:</p>
|
|
<ul>
|
|
<li> remove the copy constructor and copy-assignment operator declarations
|
|
from the slice_array class template definition in 26.3.5 <a href="lib-numerics.html#lib.template.slice.array"> [lib.template.slice.array]</a> </li>
|
|
<li> remove paragraph 3 of 26.3.5 <a href="lib-numerics.html#lib.template.slice.array"> [lib.template.slice.array]</a>
|
|
</li>
|
|
<li> remove the copy constructor declaration from 26.3.5.1 <a href="lib-numerics.html#lib.cons.slice.arr"> [lib.cons.slice.arr]</a>
|
|
</li>
|
|
<li> change paragraph 1 of 26.3.5.1 <a href="lib-numerics.html#lib.cons.slice.arr"> [lib.cons.slice.arr]</a> to read "This constructor is declared
|
|
to be private. This constructor need not be defined."</li>
|
|
<li> remove the copy-assignment operator declaration from 26.3.5.2 <a href="lib-numerics.html#lib.slice.arr.assign"> [lib.slice.arr.assign]</a>
|
|
</li>
|
|
<li> remove the first sentence of paragraph 1 of 26.3.5.2 <a href="lib-numerics.html#lib.slice.arr.assign"> [lib.slice.arr.assign]</a>
|
|
</li>
|
|
<li> Change the first two words of the second sentence of paragraph 1 of
|
|
26.3.5.2 <a href="lib-numerics.html#lib.slice.arr.assign"> [lib.slice.arr.assign]</a> to "This function."</li>
|
|
</ul>
|
|
|
|
<p>gslice_array:</p>
|
|
<ul>
|
|
<li> remove the copy constructor and copy-assignment operator declarations
|
|
from the gslice_array class template definition in 26.3.7 <a href="lib-numerics.html#lib.template.gslice.array"> [lib.template.gslice.array]</a> </li>
|
|
<li> remove the note in paragraph 3 of 26.3.7 <a href="lib-numerics.html#lib.template.gslice.array"> [lib.template.gslice.array]</a>
|
|
</li>
|
|
<li> remove the copy constructor declaration from 26.3.7.1 <a href="lib-numerics.html#lib.gslice.array.cons"> [lib.gslice.array.cons]</a>
|
|
</li>
|
|
<li> change paragraph 1 of 26.3.7.1 <a href="lib-numerics.html#lib.gslice.array.cons"> [lib.gslice.array.cons]</a> to read "This constructor is declared
|
|
to be private. This constructor need not be defined."</li>
|
|
<li> remove the copy-assignment operator declaration from 26.3.7.2 <a href="lib-numerics.html#lib.gslice.array.assign"> [lib.gslice.array.assign]</a>
|
|
</li>
|
|
<li> remove the first sentence of paragraph 1 of 26.3.7.2 <a href="lib-numerics.html#lib.gslice.array.assign"> [lib.gslice.array.assign]</a>
|
|
</li>
|
|
<li> Change the first two words of the second sentence of paragraph 1 of
|
|
26.3.7.2 <a href="lib-numerics.html#lib.gslice.array.assign"> [lib.gslice.array.assign]</a> to "This function."</li>
|
|
</ul>
|
|
|
|
<p>mask_array:</p>
|
|
<ul>
|
|
<li> remove the copy constructor and copy-assignment operator declarations
|
|
from the mask_array class template definition in 26.3.8 <a href="lib-numerics.html#lib.template.mask.array"> [lib.template.mask.array]</a> </li>
|
|
<li> remove the note in paragraph 2 of 26.3.8 <a href="lib-numerics.html#lib.template.mask.array"> [lib.template.mask.array]</a>
|
|
</li>
|
|
<li> remove the copy constructor declaration from 26.3.8.1 <a href="lib-numerics.html#lib.mask.array.cons"> [lib.mask.array.cons]</a>
|
|
</li>
|
|
<li> change paragraph 1 of 26.3.8.1 <a href="lib-numerics.html#lib.mask.array.cons"> [lib.mask.array.cons]</a> to read "This constructor is declared
|
|
to be private. This constructor need not be defined."</li>
|
|
<li> remove the first sentence of paragraph 1 of 26.3.8.2 <a href="lib-numerics.html#lib.mask.array.assign"> [lib.mask.array.assign]</a>
|
|
</li>
|
|
<li> Change the first two words of the second sentence of paragraph 1 of
|
|
26.3.8.2 <a href="lib-numerics.html#lib.mask.array.assign"> [lib.mask.array.assign]</a> to "This function."</li>
|
|
</ul>
|
|
|
|
<p>indirect_array:</p>
|
|
<ul>
|
|
<li>remove the copy constructor and copy-assignment operator declarations
|
|
from the indirect_array class definition in 26.3.9 <a href="lib-numerics.html#lib.template.indirect.array"> [lib.template.indirect.array]</a>
|
|
</li>
|
|
<li> remove the note in paragraph 2 of 26.3.9 <a href="lib-numerics.html#lib.template.indirect.array"> [lib.template.indirect.array]</a>
|
|
</li>
|
|
<li> remove the copy constructor declaration from 26.3.9.1 <a href="lib-numerics.html#lib.indirect.array.cons"> [lib.indirect.array.cons]</a>
|
|
</li>
|
|
<li> change the descriptive text in 26.3.9.1 <a href="lib-numerics.html#lib.indirect.array.cons"> [lib.indirect.array.cons]</a> to read "This constructor is
|
|
declared to be private. This constructor need not be defined."</li>
|
|
<li> remove the first sentence of paragraph 1 of 26.3.9.2 <a href="lib-numerics.html#lib.indirect.array.assign"> [lib.indirect.array.assign]</a>
|
|
</li>
|
|
<li> Change the first two words of the second sentence of paragraph 1 of
|
|
26.3.9.2 <a href="lib-numerics.html#lib.indirect.array.assign"> [lib.indirect.array.assign]</a> to "This function."</li>
|
|
</ul>
|
|
<p><i>[This wording is taken from Robert Klarer's reflector message,
|
|
c++std-lib-7827. Gabriel Dos Reis agrees that this general solution
|
|
is correct.]</i></p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>Keeping the valarray constructors private is untenable. Merely
|
|
making valarray a friend of the helper classes isn't good enough,
|
|
because access to the copy constructor is checked in the user's
|
|
environment.</p>
|
|
|
|
<p>Making the assignment operator public is not strictly necessary to
|
|
solve this problem. A majority of the LWG <i>(straw poll: 13-4)</i>
|
|
believed we should make the assignment operators public, in addition
|
|
to the copy constructors, for reasons of symmetry and user
|
|
expectation.</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>NAD/Future</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>[Toronto: some LWG members thought this was merely a QoI issue,
|
|
but most believed that it was at least a borderline defect. There was
|
|
more support for nonnormative advice to implementors than for a
|
|
normative change.]</i></p>
|
|
|
|
<p><i>[Redmond: discussed, without definite conclusion. Most LWG
|
|
members thought there was a real defect lurking here. The above
|
|
proposed resolution/rationale is from Howard, Herb, Kevlin, Martin,
|
|
and Dave.]</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="278"><h3>278. What does iterator validity mean?</h3></a><p>
|
|
<b>Section:</b> 23.2.2.4 <a href="lib-containers.html#lib.list.ops"> [lib.list.ops]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> P.J. Plauger <b>Date:</b> 27 Nov 2000</p>
|
|
<p>
|
|
Section 23.2.2.4 [lib.list.ops] states that
|
|
</p>
|
|
<pre>
|
|
void splice(iterator position, list<T, Allocator>& x);
|
|
</pre>
|
|
<p>
|
|
<i>invalidates</i> all iterators and references to list <tt>x</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
But what does the C++ Standard mean by "invalidate"? You
|
|
can still dereference the iterator to a spliced list element, but
|
|
you'd better not use it to delimit a range within the original
|
|
list. For the latter operation, it has definitely lost some of its
|
|
validity.
|
|
</p>
|
|
|
|
<p>
|
|
If we accept the proposed resolution to issue <a href="lwg-defects.html#250">250</a>,
|
|
then we'd better clarify that a "valid" iterator need no
|
|
longer designate an element within the same container as it once did.
|
|
We then have to clarify what we mean by invalidating a past-the-end
|
|
iterator, as when a vector or string grows by reallocation. Clearly,
|
|
such an iterator has a different kind of validity. Perhaps we should
|
|
introduce separate terms for the two kinds of "validity."
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Add the following text to the end of section 24.1 <a href="lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a>,
|
|
after paragraph 5:</p>
|
|
<blockquote>
|
|
An <i>invalid</i> iterator is an iterator that may be
|
|
singular. [Footnote: This definition applies to pointers, since
|
|
pointers are iterators. The effect of dereferencing an iterator that
|
|
has been invalidated is undefined.]
|
|
</blockquote>
|
|
|
|
<p><i>[post-Copenhagen: Matt provided wording.]</i></p>
|
|
|
|
<p><i>[Redmond: General agreement with the intent, some objections to
|
|
the wording. Dave provided new wording.]</i></p>
|
|
|
|
<p><i>[Curaçao: The definition of "singular" is
|
|
contentious. The 278 resolution must be made consistent with
|
|
issue <a href="lwg-defects.html#208">208</a> and 24.1/5. Furthermore, a Rationale paragraph
|
|
is required.]</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-active.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="282"><h3>282. What types does numpunct grouping refer to?</h3></a><p>
|
|
<b>Section:</b> 22.2.2.2.2 <a href="lib-locales.html#lib.facet.num.put.virtuals"> [lib.facet.num.put.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> Howard Hinnant <b>Date:</b> 5 Dec 2000</p>
|
|
<p>
|
|
Paragraph 16 mistakenly singles out integral types for inserting
|
|
thousands_sep() characters. This conflicts with the syntax for floating
|
|
point numbers described under 22.2.3.1/2.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change paragraph 16 from:</p>
|
|
|
|
<blockquote>
|
|
For integral types, punct.thousands_sep() characters are inserted into
|
|
the sequence as determined by the value returned by punct.do_grouping()
|
|
using the method described in 22.2.3.1.2 <a href="lib-locales.html#lib.facet.numpunct.virtuals"> [lib.facet.numpunct.virtuals]</a>.
|
|
</blockquote>
|
|
|
|
<p>To:</p>
|
|
|
|
<blockquote>
|
|
For arithmetic types, punct.thousands_sep() characters are inserted into
|
|
the sequence as determined by the value returned by punct.do_grouping()
|
|
using the method described in 22.2.3.1.2 <a href="lib-locales.html#lib.facet.numpunct.virtuals"> [lib.facet.numpunct.virtuals]</a>.
|
|
</blockquote>
|
|
|
|
<p><i>[
|
|
Copenhagen: Opinions were divided about whether this is actually an
|
|
inconsistency, but at best it seems to have been unintentional. This
|
|
is only an issue for floating-point output: The standard is
|
|
unambiguous that implementations must parse thousands_sep characters
|
|
when performing floating-point. The standard is also unambiguous that
|
|
this requirement does not apply to the "C" locale.
|
|
]</i></p>
|
|
|
|
<p><i>[
|
|
A survey of existing practice is needed; it is believed that some
|
|
implementations do insert thousands_sep characters for floating-point
|
|
output and others fail to insert thousands_sep characters for
|
|
floating-point input even though this is unambiguously required by the
|
|
standard.
|
|
]</i></p>
|
|
|
|
<p><i>[Post-Curaçao: the above proposed resolution is the consensus of
|
|
Howard, Bill, Pete, Benjamin, Nathan, Dietmar, Boris, and Martin.]</i></p>
|
|
|
|
<hr>
|
|
<a name="283"><h3>283. std::replace() requirement incorrect/insufficient</h3></a><p>
|
|
<b>Section:</b> 25.2.4 <a href="lib-algorithms.html#lib.alg.replace"> [lib.alg.replace]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 15 Dec 2000</p>
|
|
<p>
|
|
The requirements in 25.2.4 <a href="lib-algorithms.html#lib.alg.replace"> [lib.alg.replace]</a>, p1 that <tt>T</tt> to be
|
|
<tt>Assignable</tt> (23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a>) is not necessary or
|
|
sufficient for either of the algorithms. The algorithms require that
|
|
<tt>std::iterator_traits<ForwardIterator>::value_type</tt> be
|
|
<tt>Assignable</tt> and that both
|
|
<tt>std::iterator_traits<ForwardIterator>::value_type</tt> and be
|
|
<tt>EqualityComparable</tt> (20.1.1 <a href="lib-utilities.html#lib.equalitycomparable"> [lib.equalitycomparable]</a>) with respect to
|
|
one another.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Further discussion, from Jeremy</b>:
|
|
</p>
|
|
|
|
<p>There are a number of problems with the requires clauses for the
|
|
algorithms in 25.1 <a href="lib-algorithms.html#lib.alg.nonmodifying"> [lib.alg.nonmodifying]</a> and 25.2 <a href="lib-algorithms.html#lib.alg.modifying.operations"> [lib.alg.modifying.operations]</a>. The requires
|
|
clause of each algorithm should describe the necessary and sufficient
|
|
requirements on the inputs to the algorithm such that the algorithm
|
|
compiles and runs properly. Many of the requires clauses fail to do
|
|
this. Here is a summary of the kinds of mistakes:</p>
|
|
|
|
<ol>
|
|
<li> Use of EqualityComparable, which only puts requirements on a single
|
|
type, when in fact an equality operator is required between two
|
|
different types, typically either T and the iterators value_type
|
|
or between the value_type's of two different iterators.</li>
|
|
|
|
<li> Use of Assignable for T when in fact what was needed is Assignable
|
|
for the value_type of the iterator, and convertability from T to the
|
|
value_type of the iterator. Or for output iterators, the requirement
|
|
should be that T is writable to the iterator (output iterators do
|
|
not have value types; see issue <a href="lwg-active.html#324">324</a>).</li>
|
|
|
|
<li> Lack of a requires clause.</li>
|
|
</ol>
|
|
|
|
<p>Here is the list of algorithms that contain mistakes:</p>
|
|
<ul>
|
|
<li>25.1.2 <a href="lib-algorithms.html#lib.alg.find"> [lib.alg.find]</a>
|
|
</li>
|
|
<li>25.1.3 <a href="lib-algorithms.html#lib.alg.find.end"> [lib.alg.find.end]</a>
|
|
</li>
|
|
<li>25.1.4 <a href="lib-algorithms.html#lib.alg.find.first.of"> [lib.alg.find.first.of]</a>
|
|
</li>
|
|
<li>25.1.6 <a href="lib-algorithms.html#lib.alg.count"> [lib.alg.count]</a>
|
|
</li>
|
|
<li>25.1.7 <a href="lib-algorithms.html#lib.mismatch"> [lib.mismatch]</a>
|
|
</li>
|
|
<li>25.1.8 <a href="lib-algorithms.html#lib.alg.equal"> [lib.alg.equal]</a>
|
|
</li>
|
|
<li>25.1.9 <a href="lib-algorithms.html#lib.alg.search"> [lib.alg.search]</a>
|
|
</li>
|
|
<li>25.2.4 <a href="lib-algorithms.html#lib.alg.replace"> [lib.alg.replace]</a>
|
|
</li>
|
|
<li>25.2.5 <a href="lib-algorithms.html#lib.alg.fill"> [lib.alg.fill]</a>
|
|
</li>
|
|
<li>25.2.7 <a href="lib-algorithms.html#lib.alg.remove"> [lib.alg.remove]</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<p>Also, in the requirements for EqualityComparable, the requirement that
|
|
the operator be defined for const objects is lacking.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>20.1.1 <a href="lib-utilities.html#lib.equalitycomparable"> [lib.equalitycomparable]</a> Change p1 from</p>
|
|
|
|
<blockquote>
|
|
In Table 28, T is a type to be supplied by a C++ program instantiating
|
|
a template, a, b, and c are values of type T.
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
In Table 28, T is a type to be supplied by a C++ program instantiating
|
|
a template, a, b, and c are values of type const T.
|
|
</blockquote>
|
|
|
|
<p>25.1.2 <a href="lib-algorithms.html#lib.alg.find"> [lib.alg.find]</a> Change p1 from</p>
|
|
|
|
<blockquote>
|
|
Requires: Type T is EqualityComparable (20.1.1).
|
|
</blockquote>
|
|
|
|
<p>to </p>
|
|
|
|
<blockquote>
|
|
Requires: There must be a equality operator defined that accepts type
|
|
std::iterator_traits<InputIterator>::reference for the left operand
|
|
and const T for the right operand.
|
|
</blockquote>
|
|
|
|
|
|
<p>25.1.3 <a href="lib-algorithms.html#lib.alg.find.end"> [lib.alg.find.end]</a> Add the following requires clause</p>
|
|
|
|
<blockquote>
|
|
Requires: There must be an equality operator defined that accepts
|
|
type const std::iterator_traits<ForwardIterator1>::value_type for the
|
|
left operand and const
|
|
std::iterator_traits<ForwardIterator2>::value_type for the right
|
|
operand.
|
|
</blockquote>
|
|
|
|
<p>25.1.4 <a href="lib-algorithms.html#lib.alg.find.first.of"> [lib.alg.find.first.of]</a> Add the following requires clause</p>
|
|
|
|
<blockquote>
|
|
Requires: There must be an equality operator defined that accepts
|
|
type const std::iterator_traits<ForwardIterator1>::value_type for the
|
|
left operand and const
|
|
std::iterator_traits<ForwardIterator2>::value_type for the right
|
|
operand.
|
|
</blockquote>
|
|
|
|
|
|
<p>25.1.5 <a href="lib-algorithms.html#lib.alg.adjacent.find"> [lib.alg.adjacent.find]</a> Add the following requires clause</p>
|
|
|
|
<blockquote>
|
|
Requires: T must be EqualityComparable (20.1.1).
|
|
</blockquote>
|
|
|
|
<p>25.1.6 <a href="lib-algorithms.html#lib.alg.count"> [lib.alg.count]</a> Change p1 from</p>
|
|
|
|
<blockquote>
|
|
Requires: Type T is EqualityComparable (20.1.1).
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
Requires: There must be a equality operator defined that accepts type
|
|
std::iterator_traits<InputIterator>::reference for the left operand
|
|
and const T for the right operand.
|
|
</blockquote>
|
|
|
|
<p>25.1.7 <a href="lib-algorithms.html#lib.mismatch"> [lib.mismatch]</a> Add the following requires clause</p>
|
|
|
|
<blockquote>
|
|
Requires: There must be an equality operator defined that accepts type
|
|
std::iterator_traits<InputIterator1>::reference for the left operand
|
|
and std::iterator_traits<InputIterator2>::reference for the right operand.
|
|
</blockquote>
|
|
|
|
|
|
<p>25.1.8 <a href="lib-algorithms.html#lib.alg.equal"> [lib.alg.equal]</a> Add the following requires clause</p>
|
|
|
|
<blockquote>
|
|
Requires: There must be an equality operator defined that accepts type
|
|
std::iterator_traits<InputIterator1>::reference for the left operand
|
|
and std::iterator_traits<InputIterator2>::reference for the right operand.
|
|
</blockquote>
|
|
|
|
<p>25.1.9 <a href="lib-algorithms.html#lib.alg.search"> [lib.alg.search]</a> Add the following requires clause</p>
|
|
|
|
<blockquote>
|
|
Requires: There must be an equality operator defined that accepts
|
|
type const std::iterator_traits<ForwardIterator1>::value_type for
|
|
the left operand and const
|
|
std::iterator_traits<ForwardIterator2>::value_type for the right
|
|
operand.
|
|
</blockquote>
|
|
|
|
<p>Change change p4 from</p>
|
|
|
|
<blockquote>
|
|
Requires: Type T is EqualityComparable (20.1.1), type Size is
|
|
convertible to integral type (4.7.12.3).
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
Requires: There must be an equality operator defined that accepts
|
|
const std::iterator_traits<ForwardIterator>::value_type for the left
|
|
operand and const T for the right operand. The type Size is convertible to
|
|
integral type (4.7.12.3).
|
|
</blockquote>
|
|
|
|
<p>25.2.4 <a href="lib-algorithms.html#lib.alg.replace"> [lib.alg.replace]</a> Change p1 from</p>
|
|
|
|
<blockquote>
|
|
Requires: Type T is Assignable (23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a>) (and, for replace(),
|
|
EqualityComparable (20.1.1 <a href="lib-utilities.html#lib.equalitycomparable"> [lib.equalitycomparable]</a>)).
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
Requires: Type std::iterator_traits<ForwardIterator>::value_type
|
|
is Assignable (23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a>) and the type const T is convertible to
|
|
std::iterator_traits<ForwardIterator>::value_type. For replace(), an
|
|
equality operator must be defined that accepts type
|
|
std::iterator_traits<ForwardIterator>::reference for the left operand
|
|
and const T for the right operand.
|
|
</blockquote>
|
|
|
|
<p>and change p4 from</p>
|
|
|
|
<blockquote>
|
|
Requires: Type T is Assignable (23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a>) (and, for replace_copy(),
|
|
EqualityComparable (20.1.1 <a href="lib-utilities.html#lib.equalitycomparable"> [lib.equalitycomparable]</a>)). The ranges [first, last) and [result,
|
|
result + (last - first)) shall not overlap.
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
Requires: Both types const T and
|
|
std::iterator_traits<InputIterator>::reference are writable to the
|
|
OutputIterator type. For replace_copy() an equality operator must be
|
|
defined that accepts type
|
|
std::iterator_traits<InputIterator>::reference for the left operand
|
|
and const T for the right operand. The ranges [first, last) and [result,
|
|
result + (last - first)) shall not overlap.
|
|
</blockquote>
|
|
|
|
<p>25.2.5 <a href="lib-algorithms.html#lib.alg.fill"> [lib.alg.fill]</a> Change p1 from</p>
|
|
|
|
<blockquote>
|
|
Requires: Type T is Assignable (23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a> ). Size is convertible to an integral
|
|
type (3.9.1 <a href="basic.html#basic.fundamental"> [basic.fundamental]</a> ).
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
Requires: Type const T is writable to the OutputIterator. Size is
|
|
convertible to an integral type (3.9.1 <a href="basic.html#basic.fundamental"> [basic.fundamental]</a> ).
|
|
</blockquote>
|
|
|
|
|
|
<p>25.2.7 <a href="lib-algorithms.html#lib.alg.remove"> [lib.alg.remove]</a> Change p1 from</p>
|
|
|
|
<blockquote>
|
|
Requires: Type T is EqualityComparable (20.1.1 <a href="lib-utilities.html#lib.equalitycomparable"> [lib.equalitycomparable]</a>).
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
Requires: There must be an equality operator defined that accepts
|
|
type const std::iterator_traits<ForwardIterator>::value_type for the left
|
|
operand and const T for the right operand. The type
|
|
std::iterator_traits<ForwardIterator>::value_type must be Assignable
|
|
(23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a>).
|
|
</blockquote>
|
|
|
|
<p><i>[Curaçao: Jeremy reports he has run the changes through his
|
|
automated test tools. At the request of the LWG, Jeremy will reword
|
|
the PR in terms of valid expressions rather than "equality
|
|
operator".]</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="291"><h3>291. Underspecification of set algorithms</h3></a><p>
|
|
<b>Section:</b> 25.3.5 <a href="lib-algorithms.html#lib.alg.set.operations"> [lib.alg.set.operations]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 03 Jan 2001</p>
|
|
<p>
|
|
The standard library contains four algorithms that compute set
|
|
operations on sorted ranges: <tt>set_union</tt>, <tt>set_intersection</tt>,
|
|
<tt>set_difference</tt>, and <tt>set_symmetric_difference</tt>. Each
|
|
of these algorithms takes two sorted ranges as inputs, and writes the
|
|
output of the appropriate set operation to an output range. The elements
|
|
in the output range are sorted.
|
|
</p>
|
|
|
|
<p>
|
|
The ordinary mathematical definitions are generalized so that they
|
|
apply to ranges containing multiple copies of a given element. Two
|
|
elements are considered to be "the same" if, according to an
|
|
ordering relation provided by the user, neither one is less than the
|
|
other. So, for example, if one input range contains five copies of an
|
|
element and another contains three, the output range of <tt>set_union</tt>
|
|
will contain five copies, the output range of
|
|
<tt>set_intersection</tt> will contain three, the output range of
|
|
<tt>set_difference</tt> will contain two, and the output range of
|
|
<tt>set_symmetric_difference</tt> will contain two.
|
|
</p>
|
|
|
|
<p>
|
|
Because two elements can be "the same" for the purposes
|
|
of these set algorithms, without being identical in other respects
|
|
(consider, for example, strings under case-insensitive comparison),
|
|
this raises a number of unanswered questions:
|
|
</p>
|
|
|
|
<ul>
|
|
<li>If we're copying an element that's present in both of the
|
|
input ranges, which one do we copy it from?</li>
|
|
<li>If there are <i>n</i> copies of an element in the relevant
|
|
input range, and the output range will contain fewer copies (say
|
|
<i>m</i>) which ones do we choose? The first <i>m</i>, or the last
|
|
<i>m</i>, or something else?</li>
|
|
<li>Are these operations stable? That is, does a run of equivalent
|
|
elements appear in the output range in the same order as as it
|
|
appeared in the input range(s)?</li>
|
|
</ul>
|
|
|
|
<p>
|
|
The standard should either answer these questions, or explicitly
|
|
say that the answers are unspecified. I prefer the former option,
|
|
since, as far as I know, all existing implementations behave the
|
|
same way.
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>Add the following to the end of 25.3.5.2 <a href="lib-algorithms.html#lib.set.union"> [lib.set.union]</a> paragraph 5:</p>
|
|
<blockquote>
|
|
If [first1, last1) contains <i>m</i> elements that are equivalent to
|
|
each other and [first2, last2) contains <i>n</i> elements that are
|
|
equivalent to them, then max(<i>m</i>, <i>n</i>) of these elements
|
|
will be copied to the output range: all <i>m</i> of these elements
|
|
from [first1, last1), and the last max(<i>n-m</i>, 0) of them from
|
|
[first2, last2), in that order.
|
|
</blockquote>
|
|
|
|
<p>Add the following to the end of 25.3.5.3 <a href="lib-algorithms.html#lib.set.intersection"> [lib.set.intersection]</a> paragraph 5:</p>
|
|
<blockquote>
|
|
If [first1, last1) contains <i>m</i> elements that are equivalent to each
|
|
other and [first2, last2) contains <i>n</i> elements that are
|
|
equivalent to them, the first min(<i>m</i>, <i>n</i>) of those
|
|
elements from [first1, last1) are copied to the output range.
|
|
</blockquote>
|
|
|
|
<p>Add a new paragraph, <b>Notes</b>, after 25.3.5.4 <a href="lib-algorithms.html#lib.set.difference"> [lib.set.difference]</a>
|
|
paragraph 4:</p>
|
|
<blockquote>
|
|
If [first1, last1) contains <i>m</i> elements that are equivalent to each
|
|
other and [first2, last2) contains <i>n</i> elements that are
|
|
equivalent to them, the last max(<i>m-n</i>, 0) elements from
|
|
[first1, last1) are copied to the output range.
|
|
</blockquote>
|
|
|
|
<p>Add a new paragraph, <b>Notes</b>, after 25.3.5.5 <a href="lib-algorithms.html#lib.set.symmetric.difference"> [lib.set.symmetric.difference]</a>
|
|
paragraph 4:</p>
|
|
<blockquote>
|
|
If [first1, last1) contains <i>m</i> elements that are equivalent to
|
|
each other and [first2, last2) contains <i>n</i> elements that are
|
|
equivalent to them, then |<i>m - n</i>| of those elements will be
|
|
copied to the output range: the last <i>m - n</i> of these elements
|
|
from [first1, last1) if <i>m</i> > <i>n</i>, and the last <i>n -
|
|
m</i> of these elements from [first2, last2) if <i>m</i> < <i>n</i>.
|
|
</blockquote>
|
|
|
|
<p><i>[Curaçao: Missing Rationale and missing status comments from
|
|
Redmond made discussion difficult. For union, doesn't the standard
|
|
already say this? Howard, others think maybe so. Several thought the
|
|
PR may be "too complicated".]</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><b>Proposed resolution:</b></p>
|
|
<p>In section 24.1.4 <a href="lib-iterators.html#lib.bidirectional.iterators"> [lib.bidirectional.iterators]</a>, change the return type in table
|
|
75 from "convertible to T" to T&.</p>
|
|
|
|
<p>In section 24.1.5 <a href="lib-iterators.html#lib.random.access.iterators"> [lib.random.access.iterators]</a>, change the return type in table
|
|
76 from "convertible to T" to T&.</p>
|
|
|
|
<p><i>[Curaçao: Jeremy volunteered to work on this issue.]</i></p>
|
|
|
|
<hr>
|
|
<a name="300"><h3>300. list::merge() specification incomplete</h3></a><p>
|
|
<b>Section:</b> 23.2.2.4 <a href="lib-containers.html#lib.list.ops"> [lib.list.ops]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> John Pedretti <b>Date:</b> 23 Jan 2001</p>
|
|
<p>
|
|
The "Effects" clause for list::merge() (23.2.2.4, p23)
|
|
appears to be incomplete: it doesn't cover the case where the argument
|
|
list is identical to *this (i.e., this == &x). The requirement in the
|
|
note in p24 (below) is that x be empty after the merge which is surely
|
|
unintended in this case.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 23.2.2.4 <a href="lib-containers.html#lib.list.ops"> [lib.list.ops]</a>, replace paragraps 23-25 with:</p>
|
|
<blockquote>
|
|
<p>
|
|
23 Effects: if (&x == this) does nothing; otherwise, merges the two
|
|
sorted ranges [begin(), end()) and [x.begin(), x.end()). The result
|
|
is a range in which the elements will be sorted in non-decreasing
|
|
order according to the ordering defined by comp; that is, for every
|
|
iterator i in the range other than the first, the condition comp(*i,
|
|
*(i - 1)) will be false.
|
|
</p>
|
|
|
|
<p>
|
|
24 Notes: Stable: if (&x != this), then for equivalent elements in the
|
|
two original ranges, the elements from the original range [begin(),
|
|
end()) always precede the elements from the original range [x.begin(),
|
|
x.end()). If (&x != this) the range [x.begin(), x.end()) is empty
|
|
after the merge.
|
|
</p>
|
|
|
|
<p>
|
|
25 Complexity: At most size() + x.size() - 1 applications of comp if
|
|
(&x ! = this); otherwise, no applications of comp are performed. If
|
|
an exception is thrown other than by a comparison there are no
|
|
effects.
|
|
</p>
|
|
|
|
</blockquote>
|
|
|
|
<p><i>[Copenhagen: The original proposed resolution did not fix all of
|
|
the problems in 23.2.2.4 <a href="lib-containers.html#lib.list.ops"> [lib.list.ops]</a>, p22-25. Three different
|
|
paragraphs (23, 24, 25) describe the effects of <tt>merge</tt>.
|
|
Changing p23, without changing the other two, appears to introduce
|
|
contradictions. Additionally, "merges the argument list into the
|
|
list" is excessively vague.]</i></p>
|
|
|
|
<p><i>[Post-Curaçao: Robert Klarer provided new wording.]</i></p>
|
|
|
|
<hr>
|
|
<a name="304"><h3>304. Must <tt>*a</tt> return an lvalue when <tt>a</tt> is an input iterator?</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> Dave Abrahams <b>Date:</b> 5 Feb 2001</p>
|
|
<p>
|
|
We all "know" that input iterators are allowed to produce
|
|
values when dereferenced of which there is no other in-memory copy.
|
|
</p>
|
|
|
|
<p>
|
|
But: Table 72, with a careful reading, seems to imply that this can only be
|
|
the case if the value_type has no members (e.g. is a built-in type).
|
|
</p>
|
|
|
|
<p>The problem occurs in the following entry:</p>
|
|
|
|
<pre>
|
|
a->m pre: (*a).m is well-defined
|
|
Equivalent to (*a).m
|
|
</pre>
|
|
|
|
<p>
|
|
<tt>*a.m</tt> can be well-defined if <tt>*a</tt> is not a reference
|
|
type, but since <tt>operator->()</tt> must return a pointer for
|
|
<tt>a->m</tt> to be well-formed, it needs something to return a
|
|
pointer <i>to</i>. This seems to indicate that <tt>*a</tt> must be
|
|
buffered somewhere to make a legal input iterator.
|
|
</p>
|
|
|
|
<p>I don't think this was intentional.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p><i>[Copenhagen: the two obvious possibilities are to keep the
|
|
<tt>operator-></tt> requirement for Input Iterators, and put
|
|
in a non-normative note describing how it can be implemented with
|
|
proxies, or else moving the <tt>operator-></tt> requirement
|
|
from Input Iterator to Forward Iterator. If we do the former
|
|
we'll also have to change <tt>istreambuf_iterator</tt>, because
|
|
it has no <tt>operator-></tt>. A straw poll showed roughly equal
|
|
support for the two options.]</i></p>
|
|
<hr>
|
|
<a name="305"><h3>305. Default behavior of codecvt<wchar_t, char, mbstate_t>::length()</h3></a><p>
|
|
<b>Section:</b> 22.2.1.5.2 <a href="lib-locales.html#lib.locale.codecvt.virtuals"> [lib.locale.codecvt.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Howard Hinnant <b>Date:</b> 24 Jan 2001</p>
|
|
<p>22.2.1.5/3 introduces codecvt in part with:</p>
|
|
|
|
<blockquote>
|
|
codecvt<wchar_t,char,mbstate_t> converts between the native
|
|
character sets for tiny and wide characters. Instantiations on
|
|
mbstate_t perform conversion between encodings known to the library
|
|
implementor.
|
|
</blockquote>
|
|
|
|
<p>But 22.2.1.5.2/10 describes do_length in part with:</p>
|
|
|
|
<blockquote>
|
|
... codecvt<wchar_t, char, mbstate_t> ... return(s) the lesser of max and
|
|
(from_end-from).
|
|
</blockquote>
|
|
|
|
<p>
|
|
The semantics of do_in and do_length are linked. What one does must
|
|
be consistent with what the other does. 22.2.1.5/3 leads me to
|
|
believe that the vendor is allowed to choose the algorithm that
|
|
codecvt<wchar_t,char,mbstate_t>::do_in performs so that it makes
|
|
his customers happy on a given platform. But 22.2.1.5.2/10 explicitly
|
|
says what codecvt<wchar_t,char,mbstate_t>::do_length must
|
|
return. And thus indirectly specifies the algorithm that
|
|
codecvt<wchar_t,char,mbstate_t>::do_in must perform. I believe
|
|
that this is not what was intended and is a defect.
|
|
</p>
|
|
|
|
<p>Discussion from the -lib reflector:
|
|
|
|
<br>This proposal would have the effect of making the semantics of
|
|
all of the virtual functions in <tt>codecvt<wchar_t, char,
|
|
mbstate_t></tt> implementation specified. Is that what we want, or
|
|
do we want to mandate specific behavior for the base class virtuals
|
|
and leave the implementation specified behavior for the codecvt_byname
|
|
derived class? The tradeoff is that former allows implementors to
|
|
write a base class that actually does something useful, while the
|
|
latter gives users a way to get known and specified---albeit
|
|
useless---behavior, and is consistent with the way the standard
|
|
handles other facets. It is not clear what the original intention
|
|
was.</p>
|
|
|
|
<p>
|
|
Nathan has suggest a compromise: a character that is a widened version
|
|
of the characters in the basic execution character set must be
|
|
converted to a one-byte sequence, but there is no such requirement
|
|
for characters that are not part of the basic execution character set.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Change 22.2.1.5.2/5 from:
|
|
</p>
|
|
<p>
|
|
The instantiations required in Table 51 (lib.locale.category), namely
|
|
codecvt<wchar_t,char,mbstate_t> and
|
|
codecvt<char,char,mbstate_t>, store no characters. Stores no more
|
|
than (to_limit-to) destination elements. It always leaves the to_next
|
|
pointer pointing one beyond the last element successfully stored.
|
|
</p>
|
|
<p>
|
|
to:
|
|
</p>
|
|
<p>
|
|
Stores no more than (to_limit-to) destination elements, and leaves the
|
|
to_next pointer pointing one beyond the last element successfully
|
|
stored. codecvt<char,char,mbstate_t> stores no characters.
|
|
</p>
|
|
|
|
<p>Change 22.2.1.5.2/10 from:</p>
|
|
|
|
<blockquote>
|
|
-10- Returns: (from_next-from) where from_next is the largest value in
|
|
the range [from,from_end] such that the sequence of values in the
|
|
range [from,from_next) represents max or fewer valid complete
|
|
characters of type internT. The instantiations required in Table 51
|
|
(21.1.1.1.1), namely codecvt<wchar_t, char, mbstate_t> and
|
|
codecvt<char, char, mbstate_t>, return the lesser of max and
|
|
(from_end-from).
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-10- Returns: (from_next-from) where from_next is the largest value in
|
|
the range [from,from_end] such that the sequence of values in the range
|
|
[from,from_next) represents max or fewer valid complete characters of
|
|
type internT. The instantiation codecvt<char, char, mbstate_t> returns
|
|
the lesser of max and (from_end-from).
|
|
</blockquote>
|
|
|
|
<p><i>[Redmond: Nathan suggested an alternative resolution: same as
|
|
above, but require that, in the default encoding, a character from the
|
|
basic execution character set would map to a single external
|
|
character. The straw poll was 8-1 in favor of the proposed
|
|
resolution.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>The default encoding should be whatever users of a given platform
|
|
would expect to be the most natural. This varies from platform to
|
|
platform. In many cases there is a preexisting C library, and users
|
|
would expect the default encoding to be whatever C uses in the default
|
|
"C" locale. We could impose a guarantee like the one Nathan suggested
|
|
(a character from the basic execution character set must map to a
|
|
single external character), but this would rule out important
|
|
encodings that are in common use: it would rule out JIS, for
|
|
example, and it would rule out a fixed-width encoding of UCS-4.</p>
|
|
|
|
<p><i>[Curaçao: fixed rationale typo at the request of Ichiro Koshida;
|
|
"shift-JIS" changed to "JIS".]</i></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>Proposed resolution:</b></p>
|
|
<p>Add the following paragraph immediately after
|
|
27.6.1.1.2 <a href="lib-iostreams.html#lib.istream::sentry"> [lib.istream::sentry]</a>, p5</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
If an exception is thrown during the preparation then ios::badbit
|
|
is turned on* in is's error state.
|
|
</p>
|
|
|
|
<p>
|
|
[Footnote: This is done without causing an ios::failure to be thrown.
|
|
--- end footnote]
|
|
</p>
|
|
|
|
<p>
|
|
If (is.exceptions() & ios_base::badbit)!= 0 then the exception is
|
|
rethrown.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>And strike the following sentence from 27.6.1.1.2 <a href="lib-iostreams.html#lib.istream::sentry"> [lib.istream::sentry]</a>, p5</p>
|
|
|
|
<blockquote>
|
|
During preparation, the constructor may call setstate(failbit)
|
|
(which may throw ios_base::failure (lib.iostate.flags))
|
|
</blockquote>
|
|
|
|
<p>Add the following paragraph immediately after
|
|
27.6.2.3 <a href="lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a>, p3</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
If an exception is thrown during the preparation then ios::badbit
|
|
is turned on* in os's error state.
|
|
</p>
|
|
|
|
<p>
|
|
[Footnote: This is done without causing an ios::failure to be
|
|
thrown. --- end footnote]
|
|
</p>
|
|
|
|
<p>
|
|
If (os.exceptions() & ios_base::badbit)!= 0 then the exception
|
|
is rethrown.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>And strike the following sentence from 27.6.2.3 <a href="lib-iostreams.html#lib.ostream::sentry"> [lib.ostream::sentry]</a>, p3</p>
|
|
|
|
<blockquote>
|
|
During preparation, the constructor may call setstate(failbit)
|
|
(which may throw ios_base::failure (lib.iostate.flags))
|
|
</blockquote>
|
|
|
|
<p>(Note that the removal of the two sentences means that the ctors
|
|
will not be able to report the failure of any implementation-dependent
|
|
operations referred to in footnotes 280 and 293, unless such
|
|
operations throw an exception.)</p>
|
|
|
|
<p><i>[
|
|
Copenhagen: It was agreed that there was an issue here, but there was
|
|
disagreement about the resolution. Some LWG members argued 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.
|
|
]</i></p>
|
|
|
|
<hr>
|
|
<a name="320"><h3>320. list::assign overspecified</h3></a><p>
|
|
<b>Section:</b> 23.2.2.1 <a href="lib-containers.html#lib.list.cons"> [lib.list.cons]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Howard Hinnant <b>Date:</b> 17 May 2001</p>
|
|
<p>
|
|
Section 23.2.2.1, paragraphs 6-8 specify that list assign (both forms) have
|
|
the "effects" of a call to erase followed by a call to insert.
|
|
</p>
|
|
|
|
<p>
|
|
I would like to document that implementers have the freedom to implement
|
|
assign by other methods, as long as the end result is the same and the
|
|
exception guarantee is as good or better than the basic guarantee.
|
|
</p>
|
|
|
|
<p>
|
|
The motivation for this is to use T's assignment operator to recycle
|
|
existing nodes in the list instead of erasing them and reallocating
|
|
them with new values. It is also worth noting that, with careful
|
|
coding, most common cases of assign (everything but assignment with
|
|
true input iterators) can elevate the exception safety to strong if
|
|
T's assignment has a nothrow guarantee (with no extra memory cost).
|
|
Metrowerks does this. However I do not propose that this subtlety be
|
|
standardized. It is a QoI issue. </p>
|
|
|
|
<p>Existing practise:
|
|
Metrowerks and SGI recycle nodes, Dinkumware and Rogue Wave don't.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 23.2.2.1/7 from:</p>
|
|
|
|
<blockquote>
|
|
<p>Effects:</p>
|
|
|
|
<pre>
|
|
erase(begin(), end());
|
|
insert(begin(), first, last);
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>Effects: Replaces the contents of the list with the range [first, last).</p>
|
|
</blockquote>
|
|
|
|
<p>In 23.1.1 <a href="lib-containers.html#lib.sequence.reqmts"> [lib.sequence.reqmts]</a>, in Table 67 (sequence requirements),
|
|
add two new rows:</p>
|
|
<pre>
|
|
a.assign(i,j) void pre: i,j are not iterators into a.
|
|
Replaces elements in a with a copy
|
|
of [i, j).
|
|
|
|
a.assign(n,t) void pre: t is not a reference into a.
|
|
Replaces elements in a with n copies
|
|
of t.
|
|
</pre>
|
|
|
|
<p>Change 23.2.2.1/8 from:</p>
|
|
|
|
<blockquote>
|
|
<p>Effects:</p>
|
|
<pre>
|
|
erase(begin(), end());
|
|
insert(begin(), n, t);
|
|
</pre>
|
|
</blockquote>
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>Effects: Replaces the contents of the list with n copies of t.</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Redmond: Proposed resolution was changed slightly. Previous
|
|
version made explicit statement about exception safety, which wasn't
|
|
consistent with the way exception safety is expressed elsewhere.
|
|
Also, the change in the sequence requirements is new. Without that
|
|
change, the proposed resolution would have required that assignment of
|
|
a subrange would have to work. That too would have been
|
|
overspecification; it would effectively mandate that assignment use a
|
|
temporary. Howard provided wording.
|
|
]</i></p>
|
|
|
|
<p><i>[Curaçao: Made editorial improvement in wording; changed
|
|
"Replaces elements in a with copies of elements in [i, j)."
|
|
with "Replaces the elements of a with a copy of [i, j)."
|
|
Changes not deemed serious enough to requre rereview.]</i></p>
|
|
|
|
<hr>
|
|
<a name="323"><h3>323. abs() overloads in different headers</h3></a><p>
|
|
<b>Section:</b> 26.5 <a href="lib-numerics.html#lib.c.math"> [lib.c.math]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 4 June 2001</p>
|
|
<p>Currently the standard mandates the following overloads of
|
|
abs():</p>
|
|
|
|
<pre>
|
|
abs(long), abs(int) in <cstdlib>
|
|
|
|
abs(float), abs(double), abs(long double) in <cmath>
|
|
|
|
template<class T> T abs(const complex<T>&) in <complex>
|
|
|
|
template<class T> valarray<T> abs(const valarray<T>&); in <valarray>
|
|
</pre>
|
|
|
|
<p>
|
|
The problem is that having only some overloads visible of a function
|
|
that works on "implicitly inter-convertible" types is dangerous in
|
|
practice. The headers that get included at any point in a translation
|
|
unit can change unpredictably during program
|
|
development/maintenance. The wrong overload might be unintentionally
|
|
selected.
|
|
</p>
|
|
|
|
<p>
|
|
Currently, there is nothing that mandates the simultaneous visibility
|
|
of these overloads. Indeed, some vendors have begun fastidiously
|
|
reducing dependencies among their (public) headers as a QOI issue: it
|
|
helps people to write portable code by refusing to compile unless all
|
|
the correct headers are #included.
|
|
</p>
|
|
|
|
<p>The same issue may exist for other functions in the library.</p>
|
|
|
|
<p>Redmond: PJP reports that C99 adds two new kinds of abs: comples,
|
|
and int_max_abs.</p>
|
|
|
|
<p>Related issue: <a href="lwg-closed.html#343">343</a>.</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p><i>[Redmond: General agreement that the current situation is
|
|
somewhat fragile. No consensus on whether it's more fragile than any
|
|
number of other things, or whether there's any good way to fix it.
|
|
Walter suggests that <tt>abs</tt> should be defined for all built-in
|
|
types in both <cmath> and <cstdlib>, but that no effort
|
|
should be made to put all overloads for class types in one place.
|
|
Beman suggests closing this issue as "NAD Future", and adding a
|
|
<all> header as an extension. The <all> header would
|
|
solve a more general problem: users who can't remember which names are
|
|
defined in which headers. (See issue <a href="lwg-closed.html#343">343</a>)]</i></p>
|
|
|
|
<hr>
|
|
<a name="324"><h3>324. Do output iterators have value types?</h3></a><p>
|
|
<b>Section:</b> 24.1.2 <a href="lib-iterators.html#lib.output.iterators"> [lib.output.iterators]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 7 June 2001</p>
|
|
|
|
<p>Table 73 suggests that output iterators have value types. It
|
|
requires the expression "*a = t". Additionally, although Table 73
|
|
never lists "a = t" or "X(a) = t" in the "expressions" column, it
|
|
contains a note saying that "a = t" and "X(a) = t" have equivalent
|
|
(but nowhere specified!) semantics.</p>
|
|
|
|
<p>According to 24.1/9, t is supposed to be "a value of value type
|
|
T":</p>
|
|
|
|
<blockquote>
|
|
In the following sections, a and b denote values of 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.
|
|
</blockquote>
|
|
|
|
<p>Two other parts of the standard that are relevant to whether
|
|
output iterators have value types:</p>
|
|
|
|
<ul>
|
|
<li>24.1/1 says "All iterators i support the expression *i,
|
|
resulting in a value of some class, enumeration, or built-in type
|
|
T, called the value type of the iterator".</li>
|
|
|
|
<li>
|
|
24.3.1/1, which says "In the case of an output iterator, the types
|
|
iterator_traits<Iterator>::difference_type
|
|
iterator_traits<Iterator>::value_type are both defined as void."
|
|
</li>
|
|
</ul>
|
|
|
|
<p>The first of these passages suggests that "*i" is supposed to
|
|
return a useful value, which contradicts the note in 24.1.2/2 saying
|
|
that the only valid use of "*i" for output iterators is in an
|
|
expression of the form "*i = t". The second of these passages appears
|
|
to contradict Table 73, because it suggests that "*i"'s return value
|
|
should be void. The second passage is also broken in the case of a an
|
|
iterator type, like non-const pointers, that satisfies both the output
|
|
iterator requirements and the forward iterator requirements.</p>
|
|
|
|
<p>What should the standard say about <tt>*i</tt>'s return value when
|
|
i is an output iterator, and what should it say about that t is in the
|
|
expression "*i = t"? Finally, should the standard say anything about
|
|
output iterators' pointer and reference types?</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>24.1 p1, change</p>
|
|
|
|
<blockquote>
|
|
<p>All iterators <tt>i</tt> support the expression <tt>*i</tt>, resulting
|
|
in a value of some class, enumeration, or built-in type <tt>T</tt>,
|
|
called the value type of the iterator.</p>
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
<p>All input iterators <tt>i</tt> support the expression <tt>*i</tt>,
|
|
resulting in a value of some class, enumeration, or built-in type
|
|
<tt>T</tt>, called the value type of the iterator. All output
|
|
iterators support the expression <tt>*i = o</tt> where <tt>o</tt> is a
|
|
value of some type that is in the set of types that are <i>writable</i> to
|
|
the particular iterator type of <tt>i</tt>.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>24.1 p9, add</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
<tt>o</tt> denotes a value of some type that is writable to the
|
|
output iterator.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>Table 73, change</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
*a = t
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
*r = o
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>and change</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
*r++ = t
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
*r++ = o
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p><i>[post-Redmond: Jeremy provided wording]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>The LWG considered two options: change all of the language that
|
|
seems to imply that output iterators have value types, thus making it
|
|
clear that output iterators have no value types, or else define value
|
|
types for output iterator consistently. The LWG chose the former
|
|
option, because it seems clear that output iterators were never
|
|
intended to have value types. This was a deliberate design decision,
|
|
and any language suggesting otherwise is simply a mistake.</p>
|
|
|
|
<p>A future revision of the standard may wish to revisit this design
|
|
decision.</p>
|
|
<hr>
|
|
<a name="325"><h3>325. Misleading text in moneypunct<>::do_grouping</h3></a><p>
|
|
<b>Section:</b> 22.2.6.3.2 <a href="lib-locales.html#lib.locale.moneypunct.virtuals"> [lib.locale.moneypunct.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 02 Jul 2001</p>
|
|
<p>The Returns clause in 22.2.6.3.2, p3 says about
|
|
moneypunct<charT>::do_grouping()
|
|
</p>
|
|
|
|
<blockquote>
|
|
Returns: A pattern defined identically as the result of
|
|
numpunct<charT>::do_grouping().241)
|
|
</blockquote>
|
|
|
|
<p>Footnote 241 then reads</p>
|
|
|
|
<blockquote>
|
|
This is most commonly the value "\003" (not "3").
|
|
</blockquote>
|
|
|
|
<p>
|
|
The returns clause seems to imply that the two member functions must
|
|
return an identical value which in reality may or may not be true,
|
|
since the facets are usually implemented in terms of struct std::lconv
|
|
and return the value of the grouping and mon_grouping, respectively.
|
|
The footnote also implies that the member function of the moneypunct
|
|
facet (rather than the overridden virtual functions in moneypunct_byname)
|
|
most commonly return "\003", which contradicts the C standard which
|
|
specifies the value of "" for the (most common) C locale.
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Replace the text in Returns clause in 22.2.6.3.2, p3 with the following:</p>
|
|
|
|
<blockquote>
|
|
Returns: A pattern defined identically as, but not necessarily
|
|
equal to, the result of numpunct<charT>::do_grouping().241)
|
|
</blockquote>
|
|
|
|
<p>and replace the text in Footnote 241 with the following:</p>
|
|
|
|
<blockquote>
|
|
To specify grouping by 3s the value is "\003", not "3".
|
|
</blockquote>
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
The fundamental problem is that the description of the locale facet
|
|
virtuals serves two purposes: describing the behavior of the base
|
|
class, and describing the meaning of and constraints on the behavior
|
|
in arbitrary derived classes. The new wording makes that separation a
|
|
little bit clearer. The footnote (which is nonnormative) is not
|
|
supposed to say what the grouping is in the "C" locale or in any other
|
|
locale. It is just a reminder that the values are interpreted as small
|
|
integers, not ASCII characters.
|
|
</p>
|
|
<hr>
|
|
<a name="329"><h3>329. vector capacity, reserve and reallocation</h3></a><p>
|
|
<b>Section:</b> 23.2.4.2 <a href="lib-containers.html#lib.vector.capacity"> [lib.vector.capacity]</a>, 23.2.4.3 <a href="lib-containers.html#lib.vector.modifiers"> [lib.vector.modifiers]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Anthony Williams <b>Date:</b> 13 Jul 2001</p>
|
|
<p>
|
|
There is an apparent contradiction about which circumstances can cause
|
|
a reallocation of a vector in Section 23.2.4.2 <a href="lib-containers.html#lib.vector.capacity"> [lib.vector.capacity]</a> and
|
|
section 23.2.4.3 <a href="lib-containers.html#lib.vector.modifiers"> [lib.vector.modifiers]</a>.
|
|
</p>
|
|
|
|
<p>23.2.4.2p5 says:</p>
|
|
<blockquote>
|
|
Notes: Reallocation invalidates all the references, pointers, and iterators
|
|
referring to the elements in the sequence. It is guaranteed that no
|
|
reallocation takes place during insertions that happen after a call to
|
|
reserve() until the time when an insertion would make the size of the vector
|
|
greater than the size specified in the most recent call to reserve().
|
|
</blockquote>
|
|
|
|
<p>Which implies if I do</p>
|
|
|
|
<pre>
|
|
std::vector<int> vec;
|
|
vec.reserve(23);
|
|
vec.reserve(0);
|
|
vec.insert(vec.end(),1);
|
|
</pre>
|
|
|
|
<p>then the implementation may reallocate the vector for the insert,
|
|
as the size specified in the previous call to reserve was zero.</p>
|
|
|
|
<p>However, the previous paragraphs (23.2.4.2, p1-2) state:</p>
|
|
<blockquote>
|
|
<p>
|
|
(capacity) Returns: The total number of elements the vector
|
|
can hold without requiring reallocation
|
|
</p>
|
|
<p>
|
|
...After reserve(), capacity() is greater or equal to the
|
|
argument of reserve if reallocation happens; and equal to the previous value
|
|
of capacity() otherwise...
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>
|
|
This implies that vec.capacity() is still 23, and so the insert()
|
|
should not require a reallocation, as vec.size() is 0. This is backed
|
|
up by 23.2.4.3p1:
|
|
</p>
|
|
<blockquote>
|
|
(insert) Notes: Causes reallocation if the new size is greater than the old
|
|
capacity.
|
|
</blockquote>
|
|
|
|
<p>
|
|
Though this doesn't rule out reallocation if the new size is less
|
|
than the old capacity, I think the intent is clear.
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the wording of 23.2.4.2 <a href="lib-containers.html#lib.vector.capacity"> [lib.vector.capacity]</a> paragraph 5 to:</p>
|
|
|
|
<blockquote>
|
|
Notes: Reallocation invalidates all the references, pointers, and
|
|
iterators referring to the elements in the sequence. It is guaranteed
|
|
that no reallocation takes place during insertions that happen after a
|
|
call to reserve() until the time when an insertion would make the size
|
|
of the vector greater than the value of capacity().
|
|
</blockquote>
|
|
|
|
<p><i>[Redmond: original proposed resolution was modified slightly. In
|
|
the original, the guarantee was that there would be no reallocation
|
|
until the size would be greater than the value of capacity() after the
|
|
most recent call to reserve(). The LWG did not believe that the
|
|
"after the most recent call to reserve()" added any useful
|
|
information.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>There was general agreement that, when reserve() is called twice in
|
|
succession and the argument to the second invocation is smaller than
|
|
the argument to the first, the intent was for the second invocation to
|
|
have no effect. Wording implying that such cases have an effect on
|
|
reallocation guarantees was inadvertant.</p>
|
|
<hr>
|
|
<a name="333"><h3>333. does endl imply synchronization with the device?</h3></a><p>
|
|
<b>Section:</b> 27.6.2.7 <a href="lib-iostreams.html#lib.ostream.manip"> [lib.ostream.manip]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> PremAnand M. Rao <b>Date:</b> 27 Aug 2001</p>
|
|
<p>A footnote in 27.6.2.7 <a href="lib-iostreams.html#lib.ostream.manip"> [lib.ostream.manip]</a> states:</p>
|
|
<blockquote>
|
|
[Footnote: The effect of executing cout << endl is to insert a
|
|
newline character in the output sequence controlled by cout, then
|
|
synchronize it with any external file with which it might be
|
|
associated. --- end foonote]
|
|
</blockquote>
|
|
|
|
<p>
|
|
Does the term "file" here refer to the external device?
|
|
This leads to some implementation ambiguity on systems with fully
|
|
buffered files where a newline does not cause a flush to the device.
|
|
</p>
|
|
|
|
<p>
|
|
Choosing to sync with the device leads to significant performance
|
|
penalties for each call to endl, while not sync-ing leads to
|
|
errors under special circumstances.
|
|
</p>
|
|
|
|
<p>
|
|
I could not find any other statement that explicitly defined
|
|
the behavior one way or the other.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Remove footnote 300 from section 27.6.2.7 <a href="lib-iostreams.html#lib.ostream.manip"> [lib.ostream.manip]</a>.</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>We already have normative text saying what <tt>endl</tt> does: it
|
|
inserts a newline character and calls <tt>flush</tt>. This footnote
|
|
is at best redundant, at worst (as this issue says) misleading,
|
|
because it appears to make promises about what <tt>flush</tt>
|
|
does.</p>
|
|
<hr>
|
|
<a name="334"><h3>334. map::operator[] specification forces inefficient implementation</h3></a><p>
|
|
<b>Section:</b> 23.3.1.2 <a href="lib-containers.html#lib.map.access"> [lib.map.access]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Andrea Griffini <b>Date:</b> 02 Sep 2001</p>
|
|
<p>
|
|
The current standard describes map::operator[] using a
|
|
code example. That code example is however quite
|
|
inefficient because it requires several useless copies
|
|
of both the passed key_type value and of default
|
|
constructed mapped_type instances.
|
|
My opinion is that was not meant by the comitee to
|
|
require all those temporary copies.
|
|
</p>
|
|
|
|
<p>Currently map::operator[] behaviour is specified as: </p>
|
|
<pre>
|
|
Returns:
|
|
(*((insert(make_pair(x, T()))).first)).second.
|
|
</pre>
|
|
|
|
<p>
|
|
This specification however uses make_pair that is a
|
|
template function of which parameters in this case
|
|
will be deduced being of type const key_type& and
|
|
const T&. This will create a pair<key_type,T> that
|
|
isn't the correct type expected by map::insert so
|
|
another copy will be required using the template
|
|
conversion constructor available in pair to build
|
|
the required pair<const key_type,T> instance.
|
|
</p>
|
|
|
|
<p>If we consider calling of key_type copy constructor
|
|
and mapped_type default constructor and copy
|
|
constructor as observable behaviour (as I think we
|
|
should) then the standard is in this place requiring
|
|
two copies of a key_type element plus a default
|
|
construction and two copy construction of a mapped_type
|
|
(supposing the addressed element is already present
|
|
in the map; otherwise at least another copy
|
|
construction for each type).
|
|
</p>
|
|
|
|
<p>A simple (half) solution would be replacing the description with:</p>
|
|
<pre>
|
|
Returns:
|
|
(*((insert(value_type(x, T()))).first)).second.
|
|
</pre>
|
|
|
|
<p>This will remove the wrong typed pair construction that
|
|
requires one extra copy of both key and value.</p>
|
|
|
|
<p>However still the using of map::insert requires temporary
|
|
objects while the operation, from a logical point of view,
|
|
doesn't require any. </p>
|
|
|
|
<p>I think that a better solution would be leaving free an
|
|
implementer to use a different approach than map::insert
|
|
that, because of its interface, forces default constructed
|
|
temporaries and copies in this case.
|
|
The best solution in my opinion would be just requiring
|
|
map::operator[] to return a reference to the mapped_type
|
|
part of the contained element creating a default element
|
|
with the specified key if no such an element is already
|
|
present in the container. Also a logarithmic complexity
|
|
requirement should be specified for the operation.
|
|
</p>
|
|
|
|
<p>
|
|
This would allow library implementers to write alternative
|
|
implementations not using map::insert and reaching optimal
|
|
performance in both cases of the addressed element being
|
|
present or absent from the map (no temporaries at all and
|
|
just the creation of a new pair inside the container if
|
|
the element isn't present).
|
|
Some implementer has already taken this option but I think
|
|
that the current wording of the standard rules that as
|
|
non-conforming.
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>
|
|
Replace 23.3.1.2 <a href="lib-containers.html#lib.map.access"> [lib.map.access]</a> paragraph 1 with
|
|
</p>
|
|
<blockquote>
|
|
<p>
|
|
-1- Effects: If there is no key equivalent to x in the map, inserts
|
|
value_type(x, T()) into the map.
|
|
</p>
|
|
<p>
|
|
-2- Returns: A reference to the mapped_type corresponding to x in *this.
|
|
</p>
|
|
<p>
|
|
-3- Complexity: logarithmic.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p><i>[This is the second option mentioned above. Howard provided
|
|
wording. We may also wish to have a blanket statement somewhere in
|
|
clause 17 saying that we do not intend the semantics of sample code
|
|
fragments to be interpreted as specifing exactly how many copies are
|
|
made. See issue <a href="lwg-active.html#98">98</a> for a similar problem.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
This is the second solution described above; as noted, it is
|
|
consistent with existing practice.
|
|
</p>
|
|
|
|
<p>Note that we now need to specify the complexity explicitly, because
|
|
we are no longer defining <tt>operator[]</tt> in terms of
|
|
<tt>insert</tt>.</p>
|
|
<hr>
|
|
<a name="336"><h3>336. Clause 17 lack of references to deprecated headers</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> Detlef Vollmann <b>Date:</b> 05 Sep 2001</p>
|
|
<p>From c++std-edit-873:</p>
|
|
|
|
<p>17.4.1.2 <a href="lib-intro.html#lib.headers"> [lib.headers]</a>, Table 11. In this table, the header
|
|
<strstream> is missing.</p>
|
|
|
|
<p>This shows a general problem: The whole clause 17 refers quite
|
|
often to clauses 18 through 27, but D.7 is also a part of the standard
|
|
library (though a deprecated one).</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p><i>[Redmond: The LWG agrees that <strstream> should be added
|
|
to table 11. A review is needed to determine whether there are any
|
|
other places in clause 17 where clause D material should be referred
|
|
to. Beman will review clause 17.]</i></p>
|
|
|
|
<p><i>[Curaçao: Beman emailed wording to Matt, but not in time for the
|
|
pre-meeting mailing.]</i></p>
|
|
|
|
<hr>
|
|
<a name="338"><h3>338. is whitespace allowed between `-' and a digit?</h3></a><p>
|
|
<b>Section:</b> 22.2 <a href="lib-locales.html#lib.locale.categories"> [lib.locale.categories]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 17 Sep 2001</p>
|
|
<p>
|
|
From Stage 2 processing in 22.2.2.1.2 <a href="lib-locales.html#lib.facet.num.get.virtuals"> [lib.facet.num.get.virtuals]</a>, p8 and 9 (the
|
|
original text or the text corrected by the proposed resolution of
|
|
issue <a href="lwg-defects.html#221">221</a>) it seems clear that no whitespace is allowed
|
|
within a number, but 22.2.3.1 <a href="lib-locales.html#lib.locale.numpunct"> [lib.locale.numpunct]</a>, p2, which gives the
|
|
format for integer and floating point values, says that whitespace is
|
|
optional between a plusminus and a sign.
|
|
</p>
|
|
|
|
<p>
|
|
The text needs to be clarified to either consistently allow or
|
|
disallow whitespace between a plusminus and a sign. It might be
|
|
worthwhile to consider the fact that the C library stdio facility does
|
|
not permit whitespace embedded in numbers and neither does the C or
|
|
C++ core language (the syntax of integer-literals is given in 2.13.1 <a href="lex.html#lex.icon"> [lex.icon]</a>, that of floating-point-literals in 2.13.3 <a href="lex.html#lex.fcon"> [lex.fcon]</a> of the C++ standard).
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the first part of 22.2.3.1 <a href="lib-locales.html#lib.locale.numpunct"> [lib.locale.numpunct]</a> paragraph 2 from:</p>
|
|
<blockquote>
|
|
<p>
|
|
The syntax for number formats is as follows, where <tt>digit</tt>
|
|
represents the radix set specified by the <tt>fmtflags</tt> argument
|
|
value, <tt>whitespace</tt> is as determined by the facet
|
|
<tt>ctype<charT></tt> (22.2.1.1), and <tt>thousands-sep</tt> and
|
|
<tt>decimal-point</tt> are the results of corresponding
|
|
<tt>numpunct<charT></tt> members. Integer values have the
|
|
format:
|
|
</p>
|
|
<pre>
|
|
integer ::= [sign] units
|
|
sign ::= plusminus [whitespace]
|
|
plusminus ::= '+' | '-'
|
|
units ::= digits [thousands-sep units]
|
|
digits ::= digit [digits]
|
|
</pre>
|
|
</blockquote>
|
|
<p>to:</p>
|
|
<blockquote>
|
|
<p>
|
|
The syntax for number formats is as follows, where <tt>digit</tt>
|
|
represents the radix set specified by the <tt>fmtflags</tt> argument
|
|
value, and <tt>thousands-sep</tt> and <tt>decimal-point</tt> are the
|
|
results of corresponding <tt>numpunct<charT></tt> members.
|
|
Integer values have the format:
|
|
</p>
|
|
<pre>
|
|
integer ::= [sign] units
|
|
sign ::= plusminus
|
|
plusminus ::= '+' | '-'
|
|
units ::= digits [thousands-sep units]
|
|
digits ::= digit [digits]
|
|
</pre>
|
|
</blockquote>
|
|
<p><b>Rationale:</b></p>
|
|
<p>It's not clear whether the format described in 22.2.3.1 <a href="lib-locales.html#lib.locale.numpunct"> [lib.locale.numpunct]</a> paragraph 2 has any normative weight: nothing in the
|
|
standard says how, or whether, it's used. However, there's no reason
|
|
for it to differ gratuitously from the very specific description of
|
|
numeric processing in 22.2.2.1.2 <a href="lib-locales.html#lib.facet.num.get.virtuals"> [lib.facet.num.get.virtuals]</a>. The proposed
|
|
resolution removes all mention of "whitespace" from that format.</p>
|
|
<hr>
|
|
<a name="339"><h3>339. definition of bitmask type restricted to clause 27</h3></a><p>
|
|
<b>Section:</b> 22.2.1 <a href="lib-locales.html#lib.category.ctype"> [lib.category.ctype]</a>, 17.3.2.1.2 <a href="lib-intro.html#lib.bitmask.types"> [lib.bitmask.types]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 17 September 2001</p>
|
|
<p>
|
|
The ctype_category::mask type is declared to be an enum in 22.2.1 <a href="lib-locales.html#lib.category.ctype"> [lib.category.ctype]</a> with p1 then stating that it is a bitmask type, most
|
|
likely referring to the definition of bitmask type in 17.3.2.1.2 <a href="lib-intro.html#lib.bitmask.types"> [lib.bitmask.types]</a>, p1. However, the said definition only applies to
|
|
clause 27, making the reference in 22.2.1 somewhat dubious.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Clarify 17.3.2.1.2, p1 by changing the current text from</p>
|
|
<blockquote>
|
|
Several types defined in clause 27 are bitmask types. Each bitmask type
|
|
can be implemented as an enumerated type that overloads certain operators,
|
|
as an integer type, or as a bitset (23.3.5 <a href="lib-containers.html#lib.template.bitset"> [lib.template.bitset]</a>).
|
|
</blockquote>
|
|
<p>to read</p>
|
|
<blockquote>
|
|
Several types defined in clauses lib.language.support through
|
|
lib.input.output and Annex D are bitmask types. Each bitmask type can
|
|
be implemented as an enumerated type that overloads certain operators,
|
|
as an integer type, or as a bitset (lib.template.bitset).
|
|
</blockquote>
|
|
|
|
<p>
|
|
Additionally, change the definition in 22.2.1 to adopt the same
|
|
convention as in clause 27 by replacing the existing text with the
|
|
following (note, in particluar, the cross-reference to 17.3.2.1.2 in
|
|
22.2.1, p1):
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>22.2.1 The ctype category [lib.category.ctype]</p>
|
|
<pre>
|
|
namespace std {
|
|
class ctype_base {
|
|
public:
|
|
typedef <b><i>T</i></b> mask;
|
|
|
|
// numeric values are for exposition only.
|
|
static const mask space = 1 << 0;
|
|
static const mask print = 1 << 1;
|
|
static const mask cntrl = 1 << 2;
|
|
static const mask upper = 1 << 3;
|
|
static const mask lower = 1 << 4;
|
|
static const mask alpha = 1 << 5;
|
|
static const mask digit = 1 << 6;
|
|
static const mask punct = 1 << 7;
|
|
static const mask xdigit = 1 << 8;
|
|
static const mask alnum = alpha | digit;
|
|
static const mask graph = alnum | punct;
|
|
};
|
|
}
|
|
</pre>
|
|
|
|
<p>The type <tt>mask</tt> is a bitmask type (17.3.2.1.2 <a href="lib-intro.html#lib.bitmask.types"> [lib.bitmask.types]</a>).</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Curaçao: The LWG notes that T above should be bold-italics to be
|
|
consistent with the rest of the standard.]</i></p>
|
|
|
|
<hr>
|
|
<a name="340"><h3>340. interpretation of <tt>has_facet<Facet>(loc)</tt>
|
|
</h3></a><p>
|
|
<b>Section:</b> 22.1.1.1.1 <a href="lib-locales.html#lib.locale.category"> [lib.locale.category]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 18 Sep 2001</p>
|
|
<p>
|
|
It's unclear whether 22.1.1.1.1, p3 says that
|
|
<tt>has_facet<Facet>(loc)</tt> returns true for any <tt>Facet</tt>
|
|
from Table 51 or whether it includes Table 52 as well:
|
|
</p>
|
|
|
|
<blockquote>
|
|
For any locale <tt>loc</tt> either constructed, or returned by
|
|
locale::classic(), and any facet <tt>Facet</tt> that is a member of a
|
|
standard category, <tt>has_facet<Facet>(loc)</tt> is true. Each
|
|
locale member function which takes a <tt>locale::category</tt>
|
|
argument operates on the corresponding set of facets.
|
|
</blockquote>
|
|
|
|
<p>
|
|
It seems that it comes down to which facets are considered to be members of a
|
|
standard category. Intuitively, I would classify all the facets in Table 52 as
|
|
members of their respective standard categories, but there are an unbounded set
|
|
of them...
|
|
</p>
|
|
|
|
<p>
|
|
The paragraph implies that, for instance, <tt>has_facet<num_put<C,
|
|
OutputIterator> >(loc)</tt> must always return true. I don't think that's
|
|
possible. If it were, then <tt>use_facet<num_put<C, OutputIterator>
|
|
>(loc)</tt> would have to return a reference to a distinct object for each
|
|
valid specialization of <tt>num_put<C, OutputIteratory></tt>, which is
|
|
clearly impossible.
|
|
</p>
|
|
|
|
<p>
|
|
On the other hand, if none of the facets in Table 52 is a member of a standard
|
|
category then none of the locale member functions that operate on entire
|
|
categories of facets will work properly.
|
|
</p>
|
|
|
|
<p>
|
|
It seems that what p3 should mention that it's required (permitted?)
|
|
to hold only for specializations of <tt>Facet</tt> from Table 52 on
|
|
<tt>C</tt> from the set { <tt>char</tt>, <tt>wchar_t</tt> }, and
|
|
<tt>InputIterator</tt> and <tt>OutputIterator</tt> from the set of
|
|
{
|
|
{i,o}<tt>streambuf_iterator</tt><{<tt>char</tt>,<tt>wchar_t</tt>}<tt>></tt>
|
|
}.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 22.1.1.1.1 <a href="lib-locales.html#lib.locale.category"> [lib.locale.category]</a>, paragraph 3, change
|
|
"that is a member of a standard category" to "shown in Table 51".</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>The facets in Table 52 are an unbounded set. Locales should not be
|
|
required to contain an infinite number of facets.</p>
|
|
|
|
<p>It's not necessary to talk about which values of InputIterator and
|
|
OutputIterator must be supported. Table 51 already contains a
|
|
complete list of the ones we need.</p>
|
|
<hr>
|
|
<a name="341"><h3>341. Vector reallocation and swap</h3></a><p>
|
|
<b>Section:</b> 23.2.4.2 <a href="lib-containers.html#lib.vector.capacity"> [lib.vector.capacity]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Anthony Williams <b>Date:</b> 27 Sep 2001</p>
|
|
<p>It is a common idiom to reduce the capacity of a vector by swapping it with
|
|
an empty one:</p>
|
|
<pre>
|
|
std::vector<SomeType> vec;
|
|
// fill vec with data
|
|
std::vector<SomeType>().swap(vec);
|
|
// vec is now empty, with minimal capacity
|
|
</pre>
|
|
|
|
<p>However, the wording of 23.2.4.2 <a href="lib-containers.html#lib.vector.capacity"> [lib.vector.capacity]</a>paragraph 5 prevents
|
|
the capacity of a vector being reduced, following a call to
|
|
reserve(). This invalidates the idiom, as swap() is thus prevented
|
|
from reducing the capacity. The proposed wording for issue <a href="lwg-active.html#329">329</a> does not affect this. Consequently, the example above
|
|
requires the temporary to be expanded to cater for the contents of
|
|
vec, and the contents be copied across. This is a linear-time
|
|
operation.</p>
|
|
|
|
<p>However, the container requirements state that swap must have constant
|
|
complexity (23.1 <a href="lib-containers.html#lib.container.requirements"> [lib.container.requirements]</a> note to table 65).</p>
|
|
|
|
<p>This is an important issue, as reallocation affects the validity of
|
|
references and iterators.</p>
|
|
|
|
<p>If the wording of 23.2.4.2p5 is taken to be the desired intent, then
|
|
references and iterators remain valid after a call to swap, if they refer to
|
|
an element before the new end() of the vector into which they originally
|
|
pointed, in which case they refer to the element at the same index position.
|
|
Iterators and references that referred to an element whose index position
|
|
was beyond the new end of the vector are invalidated.</p>
|
|
|
|
<p>If the note to table 65 is taken as the desired intent, then there are two
|
|
possibilities with regard to iterators and references:</p>
|
|
|
|
<ol>
|
|
<li>All Iterators and references into both vectors are invalidated.</li>
|
|
<li>Iterators and references into either vector remain valid, and remain
|
|
pointing to the same element. Consequently iterators and references that
|
|
referred to one vector now refer to the other, and vice-versa.</li>
|
|
</ol>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Add a new paragraph after 23.2.4.2 <a href="lib-containers.html#lib.vector.capacity"> [lib.vector.capacity]</a> paragraph 5:</p>
|
|
<blockquote>
|
|
<pre>
|
|
void swap(vector<T,Allocator>& x);
|
|
</pre>
|
|
<p>
|
|
<b>Effects:</b> Exchanges the contents and capacity() of <tt>*this</tt>
|
|
with that of <tt>x</tt>.</p>
|
|
<p>
|
|
<b>Complexity:</b> Constant time.</p>
|
|
</blockquote>
|
|
|
|
<p><i>[This solves the problem reported for this issue. We may also
|
|
have a problem with a circular definition of swap() for other
|
|
containers.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
swap should be constant time. The clear intent is that it should just
|
|
do pointer twiddling, and that it should exchange all properties of
|
|
the two vectors, including their reallocation guarantees.
|
|
</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>[Howard will do a survey to find out if there are any other
|
|
places where we have a problem, where the difference between
|
|
<tt>fail()</tt> and <tt>!good()</tt> is important.]</i></p>
|
|
<hr>
|
|
<a name="347"><h3>347. locale::category and bitmask requirements</h3></a><p>
|
|
<b>Section:</b> 22.1.1.1.1 <a href="lib-locales.html#lib.locale.category"> [lib.locale.category]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> P.J. Plauger, Nathan Myers <b>Date:</b> 23 Oct 2001</p>
|
|
<p>
|
|
In 22.1.1.1.1 <a href="lib-locales.html#lib.locale.category"> [lib.locale.category]</a> paragraph 1, the category members
|
|
are described as bitmask elements. In fact, the bitmask requirements
|
|
in 17.3.2.1.2 <a href="lib-intro.html#lib.bitmask.types"> [lib.bitmask.types]</a> don't seem quite right: <tt>none</tt>
|
|
and <tt>all</tt> are bitmask constants, not bitmask elements.</p>
|
|
|
|
<p>In particular, the requirements for <tt>none</tt> interact poorly
|
|
with the requirement that the LC_* constants from the C library must
|
|
be recognizable as C++ locale category constants. LC_* values should
|
|
not be mixed with these values to make category values.</p>
|
|
|
|
<p>We have two options for the proposed resolution. Informally:
|
|
option 1 removes the requirement that LC_* values be recognized as
|
|
category arguments. Option 2 changes the category type so that this
|
|
requirement is implementable, by allowing <tt>none</tt> to be some
|
|
value such as 0x1000 instead of 0.</p>
|
|
|
|
<p>Nathan writes: "I believe my proposed resolution [Option 2] merely
|
|
re-expresses the status quo more clearly, without introducing any
|
|
changes beyond resolving the DR.</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
<b>Option 1:</b> <br>
|
|
Replace the first two paragraphs of 22.1.1.1 <a href="lib-locales.html#lib.locale.types"> [lib.locale.types]</a> with:</p>
|
|
<blockquote>
|
|
<pre>
|
|
typedef int category;
|
|
</pre>
|
|
|
|
<p>Valid category values include the <tt>locale</tt> member bitmask
|
|
elements <tt>collate</tt>, <tt>ctype</tt>, <tt>monetary</tt>,
|
|
<tt>numeric</tt>, <tt>time</tt>, and <tt>messages</tt>, each of which
|
|
represents a single locale category. In addition, <tt>locale</tt> member
|
|
bitmask constant <tt>none</tt> is defined as zero and represents no
|
|
category. And locale member bitmask constant <tt>all</tt> is defined such that
|
|
the expression</p>
|
|
<pre>
|
|
(collate | ctype | monetary | numeric | time | messages | all) == all
|
|
</pre>
|
|
<p>
|
|
is <tt>true</tt>, and represents the union of all categories. Further
|
|
the expression <tt>(X | Y)</tt>, where <tt>X</tt> and <tt>Y</tt> each
|
|
represent a single category, represents the union of the two
|
|
categories.
|
|
</p>
|
|
|
|
<p>
|
|
<tt>locale</tt> member functions expecting a <tt>category</tt>
|
|
argument require one of the <tt>category</tt> values defined above, or
|
|
the union of two or more such values. Such a <tt>category</tt>
|
|
argument identifies a set of locale categories. Each locale category,
|
|
in turn, identifies a set of locale facets, including at least those
|
|
shown in Table 51:
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>
|
|
<b>Option 2:</b> <br>
|
|
Replace the first paragraph of 22.1.1.1 <a href="lib-locales.html#lib.locale.types"> [lib.locale.types]</a> with:</p>
|
|
<blockquote>
|
|
<p>
|
|
Valid category values include the enumerated values. In addition, the
|
|
result of applying commutative operators | and & to any two valid
|
|
values is valid, and results in the setwise union and intersection,
|
|
respectively, of the argument categories. The values <tt>all</tt> and
|
|
<tt>none</tt> are defined such that for any valid value <tt>cat</tt>, the
|
|
expressions <tt>(cat | all == all)</tt>, <tt>(cat & all == cat)</tt>,
|
|
<tt>(cat | none == cat)</tt> and <tt>(cat & none == none)</tt> are
|
|
true. For non-equal values <tt>cat1</tt> and <tt>cat2</tt> of the
|
|
remaining enumerated values, <tt>(cat1 & cat2 == none)</tt> is true.
|
|
For any valid categories <tt>cat1</tt> and <tt>cat2</tt>, the result
|
|
of <tt>(cat1 & ~cat2)</tt> is valid, and equals the setwise union of
|
|
those categories found in <tt>cat1</tt> but not found in <tt>cat2</tt>.
|
|
[Footnote: it is not required that <tt>all</tt> equal the setwise union
|
|
of the other enumerated values; implementations may add extra categories.]
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Curaçao: need input from locale experts.]</i></p>
|
|
|
|
<hr>
|
|
<a name="348"><h3>348. Minor issue with std::pair operator<</h3></a><p>
|
|
<b>Section:</b> 20.2.2 <a href="lib-utilities.html#lib.pairs"> [lib.pairs]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Andy Sawyer <b>Date:</b> 23 Oct 2001</p>
|
|
<p>
|
|
The current wording of 20.2.2 [lib.pairs] p6 precludes the use of
|
|
operator< on any pair type which contains a pointer.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 20.2.2 <a href="lib-utilities.html#lib.pairs"> [lib.pairs]</a> paragraph 6, replace:</p>
|
|
<pre>
|
|
Returns: x.first < y.first || (!(y.first < x.first) && x.second <
|
|
y.second).
|
|
</pre>
|
|
<p>With:</p>
|
|
<pre>
|
|
Returns: std::less<T1>()( x.first, y.first ) ||
|
|
(!std::less<T1>()( y.first, x.first) &&
|
|
std::less<T2>()( x.second, y.second ) )
|
|
</pre>
|
|
|
|
<p><i>[Curaçao: LWG leaning toward NAD. In favor of the PR is
|
|
that it removes a trap for users. Concerns: 1) will break some
|
|
small amount of existing code (which define less and operator <
|
|
with different behavior), 2) don't have any indication of rationale
|
|
for current design (and unwilling to change without knowing
|
|
rationale), 3) consistency; pairs of ptrs would behave differenly from
|
|
individual pointers.]</i></p>
|
|
|
|
<hr>
|
|
<a name="349"><h3>349. Minor typographical error in ostream_iterator</h3></a><p>
|
|
<b>Section:</b> 24.5.2 <a href="lib-iterators.html#lib.ostream.iterator"> [lib.ostream.iterator]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Andy Sawyer <b>Date:</b> 24 Oct 2001</p>
|
|
<p>24.5.2 [lib.ostream.iterator] states:</p>
|
|
<pre>
|
|
[...]
|
|
|
|
private:
|
|
// basic_ostream<charT,traits>* out_stream; exposition only
|
|
// const char* delim; exposition only
|
|
</pre>
|
|
|
|
<p>Whilst it's clearly marked "exposition only", I suspect 'delim'
|
|
should be of type 'const charT*'.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In 24.5.2 <a href="lib-iterators.html#lib.ostream.iterator"> [lib.ostream.iterator]</a>, replace <tt>const char* delim</tt> with
|
|
<tt>const charT* delim</tt>.
|
|
</p>
|
|
<hr>
|
|
<a name="350"><h3>350. allocator<>::address</h3></a><p>
|
|
<b>Section:</b> 20.4.1.1 <a href="lib-utilities.html#lib.allocator.members"> [lib.allocator.members]</a>, 20.1.5 <a href="lib-utilities.html#lib.allocator.requirements"> [lib.allocator.requirements]</a>, 17.4.1.1 <a href="lib-intro.html#lib.contents"> [lib.contents]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Nathan Myers <b>Date:</b> 25 Oct 2001</p>
|
|
<p>See c++std-lib-9006 and c++std-lib-9007. This issue is taken
|
|
verbatim from -9007.</p>
|
|
|
|
<p>
|
|
The core language feature allowing definition of operator&() applied
|
|
to any non-builtin type makes that operator often unsafe to use in
|
|
implementing libraries, including the Standard Library. The result
|
|
is that many library facilities fail for legal user code, such as
|
|
the fragment</p>
|
|
<pre>
|
|
class A { private: A* operator&(); };
|
|
std::vector<A> aa;
|
|
|
|
class B { };
|
|
B* operator&(B&) { return 0; }
|
|
std::vector<B> ba;
|
|
</pre>
|
|
|
|
<p>
|
|
In particular, the requirements table for Allocator (Table 32) specifies
|
|
no semantics at all for member address(), and allocator<>::address is
|
|
defined in terms of unadorned operator &.
|
|
</p>
|
|
|
|
<p><i>[Curaçao: The LWG believes both examples are ill-formed.
|
|
The contained type is required to be CopyConstructible (20.1.3), and
|
|
that includes the requirement that &t return the usual types and
|
|
values. Since the CopyConstructible requirements appear to have been
|
|
written to deal with the concerns of this issue, the LWG feels it is
|
|
NAD unless someone can come up with a well-formed example exhibiting a
|
|
problem.]</i></p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In 20.4.1.1, Change the definition of allocator<>::address from:</p>
|
|
<blockquote>
|
|
Returns: &x
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<p>
|
|
Returns: The value that the built in operator&(x) would return if not
|
|
overloaded.
|
|
</p>
|
|
|
|
<p>
|
|
In 20.1.5, Table 32, add to the Notes column of the a.address(r) and
|
|
a.address(s) lines, respectively:
|
|
</p>
|
|
|
|
<pre>
|
|
allocator<T>::address(r)
|
|
allocator<T>::address(s)
|
|
</pre>
|
|
|
|
<p>In addition, in clause 17.4.1.1, add a statement:</p>
|
|
|
|
<blockquote>
|
|
The Standard Library does not apply operator& to any type for which
|
|
operator& may be overloaded.
|
|
</blockquote>
|
|
|
|
<p><i>[Curaçao: If the issues isn't NAD, suggest changing "if not
|
|
overloaded" to "ignoring all overloads".]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>The obvious implementations for std::allocator<>::address are</p>
|
|
<pre>
|
|
T* reinterpret_cast<T*>(&static_cast<char&>(o));
|
|
</pre>
|
|
|
|
<p>and</p>
|
|
|
|
<pre>
|
|
T const* reinterpret_cast<T const*>(&static_cast<char const&>(o));
|
|
</pre>
|
|
|
|
<p>
|
|
but to define them formally in terms of reinterpret_cast<> seems
|
|
to introduce semantic difficulties best avoided. Using a.address()
|
|
should not introduce unspecified or implementation-defined semantics
|
|
into a user program.</p>
|
|
<hr>
|
|
<a name="352"><h3>352. missing fpos requirements</h3></a><p>
|
|
<b>Section:</b> 21.1.2 <a href="lib-strings.html#lib.char.traits.typedefs"> [lib.char.traits.typedefs]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 2 Dec 2001</p>
|
|
<p>
|
|
<i>(1)</i>
|
|
There are no requirements on the <tt>stateT</tt> template parameter of
|
|
<tt>fpos</tt> listed in 27.4.3. The interface appears to require that
|
|
the type be at least Assignable and CopyConstructible (27.4.3.1, p1),
|
|
and I think also DefaultConstructible (to implement the operations in
|
|
Table 88).
|
|
</p>
|
|
<p>
|
|
21.1.2, p3, however, only requires that
|
|
<tt>char_traits<charT>::state_type</tt> meet the requirements of
|
|
CopyConstructible types.
|
|
</p>
|
|
<p>
|
|
<i>(2)</i>
|
|
Additionally, the <tt>stateT</tt> template argument has no
|
|
corresponding typedef in fpos which might make it difficult to use in
|
|
generic code.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Modify 21.1.2, p4 from
|
|
</p>
|
|
<p>
|
|
Requires: <tt>state_type</tt> shall meet the requirements of
|
|
CopyConstructible types (20.1.3).
|
|
</p>
|
|
<p>
|
|
Requires: state_type shall meet the requirements of Assignable
|
|
(23.1, p4), CopyConstructible (20.1.3), and
|
|
DefaultConstructible (20.1.4) types.
|
|
</p>
|
|
<p>
|
|
Add to the definition of the fpos class template the following member:
|
|
</p>
|
|
<pre>
|
|
typedef stateT state_type;
|
|
</pre>
|
|
<p>
|
|
and add to 27.4.3.1 a paragraph with the following text:
|
|
</p>
|
|
<pre>
|
|
typedef stateT state_type;
|
|
</pre>
|
|
<p>
|
|
Requires: <tt>state_type</tt> shall meet the requirements of
|
|
Assignable (23.1, p4), CopyConstructible (20.1.3), and
|
|
DefaultConstructible (20.1.4) types.
|
|
</p>
|
|
|
|
<p><i>[Curaçao: The LWG feels this is two issues, as indicated
|
|
above. The first is a defect; more I/O experts need to review
|
|
the PR. The second is questionable; who would use it? Unless
|
|
motivation is provided, the second should be considered NAD.]</i></p>
|
|
|
|
<hr>
|
|
<a name="354"><h3>354. Associative container lower/upper bound requirements</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#Ready">Ready</a> <b>Submitter:</b> Hans Aberg <b>Date:</b> 17 Dec 2001</p>
|
|
<p>
|
|
Discussions in the thread "Associative container lower/upper bound
|
|
requirements" on comp.std.c++ suggests that there is a defect in the
|
|
C++ standard, Table 69 of section 23.1.2, "Associative containers",
|
|
[lib.associative.reqmts]. It currently says:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
a.find(k): returns an iterator pointing to an element with the key equivalent to
|
|
k, or a.end() if such an element is not found.
|
|
</p>
|
|
|
|
<p>
|
|
a.lower_bound(k): returns an iterator pointing to the first element with
|
|
key not less than k.
|
|
</p>
|
|
|
|
<p>
|
|
a.upper_bound(k): returns an iterator pointing to the first element with
|
|
key greater than k.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>
|
|
We have "or a.end() if such an element is not found" for
|
|
<tt>find</tt>, but not for <tt>upper_bound</tt> or
|
|
<tt>lower_bound</tt>. As the text stands, one would be forced to
|
|
insert a new element into the container and return an iterator to that
|
|
in case the sought iterator does not exist, which does not seem to be
|
|
the intention (and not possible with the "const" versions).
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>Change Table 69 of section 23.1.2 <a href="lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a> indicated entries
|
|
to:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
a.lower_bound(k): returns an iterator pointing to the first element with
|
|
key not less than k, or a.end() if such an element is not found.
|
|
</p>
|
|
|
|
<p>
|
|
a.upper_bound(k): returns an iterator pointing to the first element with
|
|
key greater than k, or a.end() if such an element is not found.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Curaçao: LWG reviewed PR.]</i></p>
|
|
|
|
<hr>
|
|
<a name="355"><h3>355. Operational semantics for a.back()</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> Yaroslav Mironov <b>Date:</b> 23 Jan 2002</p>
|
|
|
|
<p>Table 68 "Optional Sequence Operations" in 23.1.1/12
|
|
specifies operational semantics for "a.back()" as
|
|
"*--a.end()", which may be ill-formed <i>[because calling
|
|
operator-- on a temporary (the return) of a built-in type is
|
|
ill-formed]</i>, provided a.end() returns a simple pointer rvalue
|
|
(this is almost always the case for std::vector::end(), for
|
|
example). Thus, the specification is not only incorrect, it
|
|
demonstrates a dangerous construct: "--a.end()" may
|
|
successfully compile and run as intended, but after changing the type
|
|
of the container or the mode of compilation it may produce
|
|
compile-time error. </p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the specification in table 68 "Optional Sequence
|
|
Operations" in 23.1.1/12 for "a.back()" from</p>
|
|
|
|
|
|
<blockquote>
|
|
*--a.end()
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
<p>*a.rbegin()</p>
|
|
</blockquote>
|
|
|
|
<p>and the specification for "a.pop_back()" from</p>
|
|
|
|
<blockquote>
|
|
a.erase(--a.end())
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
<p>a.erase(rbegin())</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Curaçao: LWG changed PR from "{ X::iterator tmp =
|
|
a.end(); return *--tmp; }" to "*a.rbegin()", and from
|
|
"{ X::iterator tmp = a.end(); a.erase(--tmp); }" to
|
|
"a.erase(rbegin())".]</i></p>
|
|
|
|
<p><i>[There is a second possible defect; table 68 "Optional
|
|
Sequence Operations" in the "Operational Semantics"
|
|
column uses operations present only in the "Reversible
|
|
Container" requirements, yet there is no stated dependency
|
|
between these separate requirements tables. Ask in Santa Cruz if the
|
|
LWG would like a new issue opened.]</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#New">New</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-active.html#339">339</a> is related, but not identical. The
|
|
proposed resolution if issue <a href="lwg-active.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><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>
|
|
|
|
<hr>
|
|
<a name="357"><h3>357. <cmath> float functions cannot return HUGE_VAL</h3></a><p>
|
|
<b>Section:</b> 26.5 <a href="lib-numerics.html#lib.c.math"> [lib.c.math]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Ray Lischner <b>Date:</b> 26 Feb 2002</p>
|
|
<p>
|
|
The float versions of the math functions have no meaningful value to return
|
|
for a range error. The long double versions have a value they can return,
|
|
but it isn't necessarily the most reasonable value.
|
|
</p>
|
|
|
|
<p>
|
|
Section 26.5 [lib.c.math], paragraph 5, says that C++ "adds float and long
|
|
double overloaded versions of these functions, with the same semantics,"
|
|
referring to the math functions from the C90 standard.
|
|
</p>
|
|
|
|
<p>
|
|
The C90 standard, in section 7.5.1, paragraph 3, says that functions return
|
|
"the value of the macro HUGE_VAL" when they encounter a range error.
|
|
Section 7.5, paragraph 2, defines HUGE_VAL as a macro that "expands to a
|
|
positive double expression, not necessarily representable as a float."
|
|
</p>
|
|
|
|
<p>
|
|
Therefore, the float versions of the math functions have no way to
|
|
signal a range error. <i>[Curaçao: The LWG notes that this isn't
|
|
strictly correct, since errno is set.]</i> The semantics require that they
|
|
return HUGE_VAL, but they cannot because HUGE_VAL might not be
|
|
representable as a float.
|
|
</p>
|
|
|
|
<p>
|
|
The problem with long double functions is less severe because HUGE_VAL is
|
|
representable as a long double. On the other hand, it might not be a "huge"
|
|
long double value, and might fall well within the range of normal return
|
|
values for a long double function. Therefore, it does not make sense for a
|
|
long double function to return a double (HUGE_VAL) for a range error.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Curaçao: C99 was faced with a similar problem, which they fixed by
|
|
adding HUGE_VALF and HUGE_VALL in addition to HUGE_VAL.</p>
|
|
|
|
<p>C++ must also fix, but it should be done in the context of the
|
|
general C99 based changes to C++, not via DR. Thus the LWG in Curaçao
|
|
felt the resolution should be NAD, FUTURE, but the issue is being held
|
|
open for one more meeting to ensure LWG members not present during the
|
|
discussion concur.</p>
|
|
<hr>
|
|
<a name="358"><h3>358. interpreting <tt>thousands_sep</tt> after a <tt>decimal_point</tt>
|
|
</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#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 12 Mar 2002</p>
|
|
<p>
|
|
I don't think <tt>thousands_sep</tt> is being treated correctly after
|
|
decimal_point has been seen. Since grouping applies only to the
|
|
integral part of the number, the first such occurrence should, IMO,
|
|
terminate Stage 2. (If it does not terminate it, then 22.2.2.1.2, p12
|
|
and 22.2.3.1.2, p3 need to explain how <tt>thousands_sep</tt> is to be
|
|
interpreted in the fractional part of a number.)
|
|
</p>
|
|
|
|
<p>
|
|
The easiest change I can think of that resolves this issue would be
|
|
something like below.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Change the first sentence of 22.2.2.1.2, p9 from
|
|
</p>
|
|
|
|
<blockquote>
|
|
If discard is true then the position of the character is
|
|
remembered, but the character is otherwise ignored. If it is not
|
|
discarded, then a check is made to determine if c is allowed as
|
|
the next character of an input field of the conversion specifier
|
|
returned by stage 1. If so it is accumulated.
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
If <tt>discard</tt> is true, then if <tt>'.'</tt> has not yet been
|
|
accumulated, then the position of the character is remembered, but
|
|
the character is otherwise ignored. Otherwise, if <tt>'.'</tt> has
|
|
already been accumulated, the character is discarded and Stage 2
|
|
terminates. ...
|
|
</blockquote>
|
|
|
|
<hr>
|
|
<a name="359"><h3>359. num_put<>::do_put (..., bool) undocumented</h3></a><p>
|
|
<b>Section:</b> 22.2.2.2.1 <a href="lib-locales.html#lib.facet.num.put.members"> [lib.facet.num.put.members]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 12 Mar 2002</p>
|
|
<p>22.2.2.2.1, p1:</p>
|
|
|
|
<pre>
|
|
iter_type put (iter_type out, ios_base& str, char_type fill,
|
|
bool val) const;
|
|
...
|
|
|
|
1 Returns: do_put (out, str, fill, val).
|
|
</pre>
|
|
|
|
<p>AFAICS, the behavior of do_put (..., bool) is not documented anywhere,
|
|
however, 22.2.2.2.2, p23:</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
iter_type put (iter_type out, ios_base& str, char_type fill,
|
|
bool val) const;
|
|
</pre>
|
|
|
|
|
|
Effects: If (str.flags() & ios_base::boolalpha) == 0 then do
|
|
out = do_put(out, str, fill, (int)val)
|
|
Otherwise do
|
|
<pre>
|
|
string_type s =
|
|
val ? use_facet<ctype<charT> >(loc).truename()
|
|
: use_facet<ctype<charT> >(loc).falsename();
|
|
</pre>
|
|
and then insert the characters of s into out. <i>out</i>.
|
|
</blockquote>
|
|
|
|
<p>
|
|
This means that the bool overload of <tt>do_put()</tt> will never be called,
|
|
which contradicts the first paragraph. Perhaps the declaration
|
|
should read <tt>do_put()</tt>, and not <tt>put()</tt>?
|
|
</p>
|
|
|
|
<p>
|
|
Note also that there is no <b>Returns</b> clause for this function, which
|
|
should probably be corrected, just as should the second occurrence
|
|
of <i>"out."</i> in the text.
|
|
</p>
|
|
|
|
<p>
|
|
I think the least invasive change to fix it would be something like
|
|
the following:
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In 22.2.2.2.2, p23, make the following changes
|
|
</p>
|
|
|
|
<blockquote>
|
|
Replace <tt>put()</tt> with <tt>do_put()</tt> in the declaration
|
|
of the member function.
|
|
</blockquote>
|
|
|
|
<blockquote>
|
|
Change the <b>Effects</b> clause to a <b>Returns</b> clause (to
|
|
avoid the requirement to call <tt>do_put(..., int)</tt> from <tt>
|
|
do_put (..., bool))</tt>
|
|
like so:
|
|
</blockquote>
|
|
|
|
<blockquote>
|
|
23 <b>Returns</b>: If <tt>(str.flags() &
|
|
ios_base::boolalpha) == 0</tt> then
|
|
<tt>do_put (out, str, fill, (int)val)</tt>
|
|
Otherwise the function obtains a string <tt>s</tt> as if by
|
|
<pre>
|
|
string_type s =
|
|
val ? use_facet<ctype<charT> >(loc).truename()
|
|
: use_facet<ctype<charT> >(loc).falsename();
|
|
</pre>
|
|
and then inserts each character <tt>c</tt> of s into out via
|
|
<tt>*out++ = c</tt>
|
|
and returns <tt>out</tt>.
|
|
</blockquote>
|
|
|
|
<hr>
|
|
<a name="360"><h3>360. locale mandates inefficient implementation</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#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 12 Mar 2002</p>
|
|
<p>
|
|
22.1.1, p7 (copied below) allows iostream formatters and extractors
|
|
to make assumptions about the values returned from facet members.
|
|
However, such assumptions are apparently not guaranteed to hold
|
|
in other cases (e.g., when the facet members are being called directly
|
|
rather than as a result of iostream calls, or between successive
|
|
calls to the same iostream functions with no interevening calls to
|
|
<tt>imbue()</tt>, or even when the facet member functions are called
|
|
from other member functions of other facets). This restriction
|
|
prevents locale from being implemented efficiently.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the first sentence in 22.1.1, p7 from</p>
|
|
<blockquote>
|
|
In successive calls to a locale facet member function during
|
|
a call to an iostream inserter or extractor or a streambuf member
|
|
function, the returned result shall be identical. [Note: This
|
|
implies that such results may safely be reused without calling
|
|
the locale facet member function again, and that member functions
|
|
of iostream classes cannot safely call <tt>imbue()</tt>
|
|
themselves, except as specified elsewhere. --end note]
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
In successive calls to a locale facet member function on a facet
|
|
object installed in the same locale, the returned result shall be
|
|
identical. ...
|
|
</blockquote>
|
|
|
|
<hr>
|
|
<a name="361"><h3>361. num_get<>::do_get (..., void*&) checks grouping</h3></a><p>
|
|
<b>Section:</b> 22.2.2.2.2 <a href="lib-locales.html#lib.facet.num.put.virtuals"> [lib.facet.num.put.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 12 Mar 2002</p>
|
|
<p>
|
|
22.2.2.2.2, p12 specifies that <tt>thousands_sep</tt> is to be inserted only
|
|
for integral types (issue 282 suggests that this should be done for
|
|
all arithmetic types).
|
|
</p>
|
|
|
|
<p>
|
|
22.2.2.1.2, p12 requires that grouping be checked for all extractors
|
|
including that for <tt>void*</tt>.
|
|
</p>
|
|
|
|
<p>
|
|
I don't think that's right. <tt>void*</tt> values should not be checked for
|
|
grouping, should they? (Although if they should, then <tt>num_put</tt> needs
|
|
to write them out, otherwise their extraction will fail.)
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Change the first sentence of 22.2.2.2.2, p12 from
|
|
</p>
|
|
<blockquote>
|
|
Digit grouping is checked. That is, the positions of discarded
|
|
separators is examined for consistency with
|
|
use_facet<numpunct<charT> >(loc).grouping().
|
|
If they are not consistent then ios_base::failbit is assigned
|
|
to err.
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
<blockquote>
|
|
Except for conversions to void*, digit grouping is checked...
|
|
</blockquote>
|
|
|
|
<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#New">New</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>
|
|
<hr>
|
|
<a name="363"><h3>363. Missing exception specification in 27.4.2.1.1</h3></a><p>
|
|
<b>Section:</b> 27.4.2.1.1 <a href="lib-iostreams.html#lib.ios::failure"> [lib.ios::failure]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Walter Brown <b>Date:</b> 20 May 2002</p>
|
|
<p>
|
|
The destructor of ios_base::failure should have an empty throw
|
|
specification, because the destructor of its base class, exception, is
|
|
declared in this way.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the destructor to</p>
|
|
<pre>
|
|
virtual ~failure() throw();
|
|
</pre>
|
|
<hr>
|
|
<a name="364"><h3>364. Inconsistent wording in 27.5.2.4.2</h3></a><p>
|
|
<b>Section:</b> 27.5.2.4.2 <a href="lib-iostreams.html#lib.streambuf.virt.buffer"> [lib.streambuf.virt.buffer]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Walter Brown <b>Date:</b> 10 May 2002</p>
|
|
<p>
|
|
27.5.2.4.2 <a href="lib-iostreams.html#lib.streambuf.virt.buffer"> [lib.streambuf.virt.buffer]</a> paragraph 1 is inconsistent with the Effects
|
|
clause for seekoff.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Make this paragraph, the Effects clause for setbuf, consistent in wording
|
|
with the Effects clause for seekoff in paragraph 3 by amending paragraph 1
|
|
to indicate the purpose of setbuf:
|
|
</p>
|
|
|
|
<p>Original text:</p>
|
|
|
|
<blockquote>
|
|
1 Effects: Performs an operation that is defined separately for each
|
|
class derived from basic_streambuf in this clause (27.7.1.3, 27.8.1.4).
|
|
</blockquote>
|
|
|
|
<p>Proposed text:</p>
|
|
|
|
<blockquote>
|
|
1 Effects: Influences stream buffering in a way that is defined separately
|
|
for each class derived from basic_streambuf in this clause
|
|
(27.7.1.3, 27.8.1.4).
|
|
</blockquote>
|
|
|
|
<hr>
|
|
<a name="365"><h3>365. Lack of const-qualification in clause 27</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#New">New</a> <b>Submitter:</b> Walter Brown <b>Date:</b> 10 May 2002</p>
|
|
<p>
|
|
None of the following member functions are declared const, but we
|
|
believe each should be. See document N1360 for details and rationale.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 27.5.2 and 27.5.2.2.3</p>
|
|
<p>Replace</p>
|
|
<pre>
|
|
streamsize in_avail();
|
|
</pre>
|
|
<p>with</p>
|
|
<pre>
|
|
streamsize in_avail() const;
|
|
</pre>
|
|
|
|
<p>In 27.5.2 and 27.5.2.4.3, and 27.8.1.1 and 27.8.1.4</p>
|
|
<p>Replace</p>
|
|
<pre>
|
|
virtual streamsize showmanyc();
|
|
</pre>
|
|
<p>with</p>
|
|
<pre>
|
|
virtual streamsize showmanyc() const;
|
|
</pre>
|
|
|
|
<p>In 27.6.1.1 and 27.6.1.3</p>
|
|
<p>Replace</p>
|
|
<pre>
|
|
pos_type tellg();
|
|
</pre>
|
|
<p>with</p>
|
|
<pre>
|
|
pos_type tellg() const;
|
|
</pre>
|
|
|
|
<p>This requires additional change, because paragraph 37 describes the
|
|
return value in terms of calls to non-const member functions. Either of
|
|
the two following solutions would allow tellg to be declared const.</p>
|
|
|
|
<p>Option 1: Implementers may cast away const-ness, to allow calling the
|
|
non-const rdbuf.</p>
|
|
<p>In paragraph 37, replace:</p>
|
|
<pre>
|
|
.... rdbuf()
|
|
->pubseekoff(0, cur, in).
|
|
</pre>
|
|
<p>by</p>
|
|
<pre>
|
|
.... const_cast<basic_istream<charT, traits>*>(this)->rdbuf()
|
|
->pubseekoff(0, cur, in).
|
|
</pre>
|
|
|
|
<p>Option 2: Provide const member functions to do the job. The proposals in
|
|
a later section (specifically, the modifications concerning rdbuf
|
|
throughout the iostream library) meet most of this need; we would also
|
|
need the following addition to basic_streambuf:</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
basic_streambuf<charT,traits>::pos_type
|
|
basic_streambuf<charT,traits>::position(ios_base::openmode mode =
|
|
ios_base::in|ios_base::out)
|
|
const;
|
|
</pre>
|
|
<p>Effects: same as calling basic_streambuf::pubseekoff(0, ios base::cur, mode)</p>
|
|
</blockquote>
|
|
|
|
<p>In 27.6.2.1 and 27.6.2.4</p>
|
|
<p>Replace</p>
|
|
<pre>
|
|
pos_type tellp();
|
|
</pre>
|
|
<p>with</p>
|
|
<pre>
|
|
pos_type tell() const;
|
|
</pre>
|
|
|
|
<p>This requires additional change; see the discussion for tellg() above.</p>
|
|
|
|
<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>
|
|
bool is_open();
|
|
</pre>
|
|
<p>with</p>
|
|
<pre>
|
|
bool is_open() const;
|
|
</pre>
|
|
<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#New">New</a> <b>Submitter:</b> Walter Brown <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><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="367"><h3>367. remove_copy/remove_copy_if and Input Iterators</h3></a><p>
|
|
<b>Section:</b> 25.2.7 <a href="lib-algorithms.html#lib.alg.remove"> [lib.alg.remove]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Anthony Williams <b>Date:</b> 13 May 2002</p>
|
|
<p>
|
|
remove_copy and remove_copy_if (25.2.7 <a href="lib-algorithms.html#lib.alg.remove"> [lib.alg.remove]</a>) permit their
|
|
input range to be marked with Input Iterators. However, since two
|
|
operations are required against the elements to copy (comparison and
|
|
assigment), when the input range uses Input Iterators, a temporary
|
|
copy must be taken to avoid dereferencing the iterator twice. This
|
|
therefore requires the value type of the InputIterator to be
|
|
CopyConstructible. If the iterators are at least Forward Iterators,
|
|
then the iterator can be dereferenced twice, or a reference to the
|
|
result maintained, so the temporary is not required.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Add "If InputIterator does not meet the requirements of forward
|
|
iterator, then the value type of InputIterator must be copy
|
|
constructible. Otherwise copy constructible is not required." to
|
|
25.2.7 <a href="lib-algorithms.html#lib.alg.remove"> [lib.alg.remove]</a> paragraph 6.
|
|
</p>
|
|
<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#New">New</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>
|
|
<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#New">New</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>
|
|
At the end of header <iostream> synopsis in 27.3 <a href="lib-iostreams.html#lib.iostream.objects"> [lib.iostream.objects]</a>
|
|
</p>
|
|
|
|
<pre>
|
|
namespace std
|
|
{
|
|
... extern istream cin; ...
|
|
</pre>
|
|
|
|
<p>add the following lines</p>
|
|
|
|
<pre>
|
|
namespace
|
|
{
|
|
ios_base::Init <some_implementation_defined_name>;
|
|
}
|
|
}
|
|
</pre>
|
|
<hr>
|
|
<a name="370"><h3>370. Minor error in basic_istream::get</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#New">New</a> <b>Submitter:</b> Ray Lischner <b>Date:</b> 15 Jul 2002</p>
|
|
<p>Defect report for description of basic_istream::get (section 27.6.1.3 <a href="lib-iostreams.html#lib.istream.unformatted"> [lib.istream.unformatted]</a>), paragraph 15. The description for the get function
|
|
with the following signature:</p>
|
|
|
|
<pre>
|
|
basic_istream<charT,traits>& get(basic_streambuf<char_type,traits>&
|
|
sb);
|
|
</pre>
|
|
|
|
<p>is incorrect. It reads</p>
|
|
|
|
<blockquote>
|
|
Effects: Calls get(s,n,widen('\n'))
|
|
</blockquote>
|
|
|
|
<p>which I believe should be:</p>
|
|
|
|
<blockquote>
|
|
Effects: Calls get(sb,widen('\n'))
|
|
</blockquote>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the <b>Effects</b> paragraph to:</p>
|
|
<blockquote>
|
|
Effects: Calls get(sb,widen('\n'))
|
|
</blockquote>
|
|
<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#New">New</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-closed.html#130">130</a>.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<hr>
|
|
<a name="372"><h3>372. Inconsistent description of stdlib exceptions</h3></a><p>
|
|
<b>Section:</b> 17.4.4.8 <a href="lib-intro.html#lib.res.on.exception.handling"> [lib.res.on.exception.handling]</a>, 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> Randy Maddox <b>Date:</b> 22 Jul 2002</p>
|
|
|
|
<p>Paragraph 3 under clause 17.4.4.8 <a href="lib-intro.html#lib.res.on.exception.handling"> [lib.res.on.exception.handling]</a>, Restrictions on
|
|
Exception Handling, states that "Any other functions defined in the
|
|
C++ Standard Library that do not have an exception-specification may
|
|
throw implementation-defined exceptions unless otherwise specified."
|
|
This statement is followed by a reference to footnote 178 at the
|
|
bottom of that page which states, apparently in reference to the C++
|
|
Standard Library, that "Library implementations are encouraged (but
|
|
not required) to report errors by throwing exceptions from (or derived
|
|
from) the standard exceptions."</p>
|
|
|
|
<p>These statements appear to be in direct contradiction to clause
|
|
18.6.1 <a href="lib-support.html#lib.exception"> [lib.exception]</a>, which states "The class exception defines the
|
|
base class for the types of objects thrown as exceptions by the C++
|
|
Standard library components ...".</p>
|
|
|
|
<p>Is this inconsistent?</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<hr>
|
|
<a name="373"><h3>373. Are basic_istream and basic_ostream to use (exceptions()&badbit) != 0 ?</h3></a><p>
|
|
<b>Section:</b> 27.6.1.2.1 <a href="lib-iostreams.html#lib.istream.formatted.reqmts"> [lib.istream.formatted.reqmts]</a>, 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#New">New</a> <b>Submitter:</b> Keith Baker <b>Date:</b> 23 Jul 2002</p>
|
|
|
|
<p>
|
|
In 27.6.1.2.1 <a href="lib-iostreams.html#lib.istream.formatted.reqmts"> [lib.istream.formatted.reqmts]</a> and 27.6.2.5.1 <a href="lib-iostreams.html#lib.ostream.formatted.reqmts"> [lib.ostream.formatted.reqmts]</a>
|
|
(exception()&badbit) != 0 is used in testing for rethrow, yet
|
|
exception() is the constructor to class std::exception in 18.6.1 <a href="lib-support.html#lib.exception"> [lib.exception]</a> that has no return type. Should member function
|
|
exceptions() found in 27.4.4 <a href="lib-iostreams.html#lib.ios"> [lib.ios]</a> be used instead?
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
</p>
|
|
<hr>
|
|
<a name="374"><h3>374. moneypunct::frac_digits returns int not unsigned</h3></a><p>
|
|
<b>Section:</b> 22.2.6.3.1 <a href="lib-locales.html#lib.locale.moneypunct.members"> [lib.locale.moneypunct.members]</a>, 22.2.6.3.2 <a href="lib-locales.html#lib.locale.moneypunct.virtuals"> [lib.locale.moneypunct.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Ray Lischner <b>Date:</b> 8 Aug 2002</p>
|
|
<p>
|
|
In section 22.2.6.3.1 <a href="lib-locales.html#lib.locale.moneypunct.members"> [lib.locale.moneypunct.members]</a>, frac_digits() returns type
|
|
"int". This implies that frac_digits() might return a negative value,
|
|
but a negative value is nonsensical. It should return "unsigned".
|
|
</p>
|
|
|
|
<p>
|
|
Similarly, in section 22.2.6.3.2 <a href="lib-locales.html#lib.locale.moneypunct.virtuals"> [lib.locale.moneypunct.virtuals]</a>, do_frac_digits()
|
|
should return "unsigned".
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<hr>
|
|
<a name="375"><h3>375. basic_ios should be ios_base in 27.7.1.3</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#New">New</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, Table 91, and paragraph
|
|
14 all contain references to "basic_ios::" which should be
|
|
"ios_base::".
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Change all references to "basic_ios" in Table 90, Table 91, and
|
|
paragraph 14 to "ios_base".
|
|
</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#New">New</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><b>Proposed resolution:</b></p>
|
|
<hr>
|
|
<a name="377"><h3>377. basic_string::insert and length_error</h3></a><p>
|
|
<b>Section:</b> 21.3.5.4 <a href="lib-strings.html#lib.string::insert"> [lib.string::insert]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Ray Lischner <b>Date:</b> 16 Aug 2002</p>
|
|
<p>
|
|
Section 21.3.5.4 <a href="lib-strings.html#lib.string::insert"> [lib.string::insert]</a>, paragraph 4, contains the following,
|
|
"Then throws length_error if size() >= npos - rlen."
|
|
</p>
|
|
|
|
<p>
|
|
Related to DR 83, this sentence should probably be removed.
|
|
</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#New">New</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>
|
|
Suggest to replace 22.1.1 <a href="lib-locales.html#lib.locale"> [lib.locale]</a>, p6 with
|
|
</p>
|
|
<pre>
|
|
-6- Unless assigned a new value, locale objects are immutable;
|
|
once a facet reference is obtained from it, that reference
|
|
remains usable as long as the locale object itself exists
|
|
or until the locale object is assigned the value of another,
|
|
distinct locale object.
|
|
</pre>
|
|
<hr>
|
|
<a name="379"><h3>379. nonsensical ctype::do_widen() requirement</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#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 6 Sep 2002</p>
|
|
<p>
|
|
The last sentence in 22.2.1.1.2, p11 below doesn't seem to make sense.
|
|
</p>
|
|
<pre>
|
|
charT do_widen (char c) const;
|
|
|
|
-11- Effects: Applies the simplest reasonable transformation from
|
|
a char value or sequence of char values to the corresponding
|
|
charT value or values. The only characters for which unique
|
|
transformations are required are those in the basic source
|
|
character set (2.2). For any named ctype category with a
|
|
ctype<charT> facet ctw and valid ctype_base::mask value
|
|
M (is(M, c) || !ctw.is(M, do_widen(c))) is true.
|
|
</pre>
|
|
<p>
|
|
Shouldn't the last sentence instead read
|
|
</p>
|
|
<pre>
|
|
For any named ctype category with a ctype<char> facet ctc
|
|
and valid ctype_base::mask value M
|
|
(ctc.is(M, c) || !is(M, do_widen(c))) is true.
|
|
</pre>
|
|
<p>
|
|
I.e., if the narrow character c is not a member of a class of
|
|
characters then neither is the widened form of c. (To paraphrase
|
|
footnote 224.)
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Replace the last sentence of 22.2.1.1.2 <a href="lib-locales.html#lib.locale.ctype.virtuals"> [lib.locale.ctype.virtuals]</a>, p11 with the
|
|
following text:
|
|
</p>
|
|
<pre>
|
|
For any named ctype category with a ctype<char> facet ctc
|
|
and valid ctype_base::mask value M
|
|
(ctc.is(M, c) || !is(M, do_widen(c))) is true.
|
|
</pre>
|
|
<hr>
|
|
<a name="380"><h3>380. typos in codecvt tables 53 and 54</h3></a><p>
|
|
<b>Section:</b> 22.2.1.5.2 <a href="lib-locales.html#lib.locale.codecvt.virtuals"> [lib.locale.codecvt.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 6 Sep 2002</p>
|
|
<p>
|
|
Tables 53 and 54 in 22.2.1.5.2 <a href="lib-locales.html#lib.locale.codecvt.virtuals"> [lib.locale.codecvt.virtuals]</a> are both titled "convert
|
|
result values," when surely "do_in/do_out result values" must have
|
|
been intended for Table 53 and "do_unshift result values" for Table
|
|
54.
|
|
</p>
|
|
<p>
|
|
Table 54, row 3 says that the meaning of partial is "more characters
|
|
needed to be supplied to complete termination." The function is not
|
|
supplied any characters, it is given a buffer which it fills with
|
|
characters or, more precisely, destination elements (i.e., an escape
|
|
sequence). So partial means that space for more than (to_limit - to)
|
|
destination elements was needed to terminate a sequence given the
|
|
value of state.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Change the title of Table 53 to "do_in/do_out result values" and
|
|
the title of Table 54 to "do_unshift result values."
|
|
</p>
|
|
<p>
|
|
Change the text in Table 54, row 3, under the heading Meaning to
|
|
"space for more than (to_limit - to) destination elements was
|
|
needed to terminate a sequence given the value of state."
|
|
</p>
|
|
<hr>
|
|
<a name="381"><h3>381. detection of invalid mbstate_t in codecvt</h3></a><p>
|
|
<b>Section:</b> 22.2.1.5.2 <a href="lib-locales.html#lib.locale.codecvt.virtuals"> [lib.locale.codecvt.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 6 Sep 2002</p>
|
|
<p>
|
|
All but one codecvt member functions that take a state_type argument
|
|
list as one of their preconditions that the state_type argument have
|
|
a valid value. However, according to 22.2.1.5.2, p6,
|
|
codecvt::do_unshift() is the only codecvt member that is supposed to
|
|
return error if the state_type object is invalid.
|
|
</p>
|
|
|
|
<p>
|
|
It seems to me that the treatment of state_type by all codecvt member
|
|
functions should be the same and the current requirements should be
|
|
changed. Since the detection of invalid state_type values may be
|
|
difficult in general or computationally expensive in some specific
|
|
cases, I propose the following:
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Add a new paragraph before 22.2.1.5.2, p5, and after the function
|
|
declaration below
|
|
</p>
|
|
<pre>
|
|
result do_unshift(stateT& state,
|
|
externT* to, externT* to_limit, externT*& to_next) const;
|
|
</pre>
|
|
<p>
|
|
as follows:
|
|
</p>
|
|
<pre>
|
|
Requires: (to <= to_end) well defined and true; state initialized,
|
|
if at the beginning of a sequence, or else equal to the result of
|
|
converting the preceding characters in the sequence.
|
|
</pre>
|
|
<p>
|
|
and change the text in Table 54, row 4, under the heading Meaning
|
|
from
|
|
</p>
|
|
<pre>
|
|
state has invalid value
|
|
</pre>
|
|
<p>
|
|
to
|
|
</p>
|
|
<pre>
|
|
an unspecified error has occurred
|
|
</pre>
|
|
<p>
|
|
The return value of error should allow implementers to detect and
|
|
report invalid state values but shouldn't require it, hence the
|
|
word "unspecified" in the new wording.
|
|
</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#New">New</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>----- End of document -----</p>
|
|
</body>
|
|
</html>
|