mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-29 15:56:35 +08:00
50b30e0bf3
2001-12-02 Phil Edwards <pme@gcc.gnu.org> * docs/html/ext/howto.html: Update list of implemented DRs. * docs/html/ext/lwg-active.html: Import R20 from upstream. * docs/html/ext/lwg-defects.html: Import R20 from upstream. From-SVN: r47540
5604 lines
250 KiB
HTML
5604 lines
250 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/01-0052 = WG21 N1337</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="left">Date:</td>
|
|
<td align="left">09 Nov 2001</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@research.att.com></td>
|
|
</tr>
|
|
</table>
|
|
<h1>C++ Standard Library Active Issues List (Revision 20)</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++">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>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-active.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-active.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-active.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-active.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-active.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-active.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-active.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-active.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> identities 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="76"><h3>76. Can a <tt>codecvt</tt> facet always convert one internal character at a time?</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#Ready">Ready</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 25 Sep 1998</p>
|
|
<p>This issue concerns the requirements on classes derived from
|
|
<tt>codecvt</tt>, including user-defined classes. What are the
|
|
restrictions on the conversion from external characters
|
|
(e.g. <tt>char</tt>) to internal characters (e.g. <tt>wchar_t</tt>)?
|
|
Or, alternatively, what assumptions about <tt>codecvt</tt> facets can
|
|
the I/O library make? </p>
|
|
|
|
<p>The question is whether it's possible to convert from internal
|
|
characters to external characters one internal character at a time,
|
|
and whether, given a valid sequence of external characters, it's
|
|
possible to pick off internal characters one at a time. Or, to put it
|
|
differently: given a sequence of external characters and the
|
|
corresponding sequence of internal characters, does a position in the
|
|
internal sequence correspond to some position in the external
|
|
sequence? </p>
|
|
|
|
<p>To make this concrete, suppose that <tt>[first, last)</tt> is a
|
|
sequence of <i>M</i> external characters and that <tt>[ifirst,
|
|
ilast)</tt> is the corresponding sequence of <i>N</i> internal
|
|
characters, where <i>N > 1</i>. That is, <tt>my_encoding.in()</tt>,
|
|
applied to <tt>[first, last)</tt>, yields <tt>[ifirst,
|
|
ilast)</tt>. Now the question: does there necessarily exist a
|
|
subsequence of external characters, <tt>[first, last_1)</tt>, such
|
|
that the corresponding sequence of internal characters is the single
|
|
character <tt>*ifirst</tt>?
|
|
</p>
|
|
|
|
<p>(What a "no" answer would mean is that
|
|
<tt>my_encoding</tt> translates sequences only as blocks. There's a
|
|
sequence of <i>M</i> external characters that maps to a sequence of
|
|
<i>N</i> internal characters, but that external sequence has no
|
|
subsequence that maps to <i>N-1</i> internal characters.) </p>
|
|
|
|
<p>Some of the wording in the standard, such as the description of
|
|
<tt>codecvt::do_max_length</tt> (22.2.1.5.2 <a href="lib-locales.html#lib.locale.codecvt.virtuals"> [lib.locale.codecvt.virtuals]</a>,
|
|
paragraph 11) and <tt>basic_filebuf::underflow</tt> (27.8.1.4 <a href="lib-iostreams.html#lib.filebuf.virtuals"> [lib.filebuf.virtuals]</a>, paragraph 3) suggests that it must always be
|
|
possible to pick off internal characters one at a time from a sequence
|
|
of external characters. However, this is never explicitly stated one
|
|
way or the other. </p>
|
|
|
|
<p>This issue seems (and is) quite technical, but it is important if
|
|
we expect users to provide their own encoding facets. This is an area
|
|
where the standard library calls user-supplied code, so a well-defined
|
|
set of requirements for the user-supplied code is crucial. Users must
|
|
be aware of the assumptions that the library makes. This issue affects
|
|
positioning operations on <tt>basic_filebuf</tt>, unbuffered input,
|
|
and several of <tt>codecvt</tt>'s member functions. </p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Add the following text as a new paragraph, following 22.2.1.5.2 <a href="lib-locales.html#lib.locale.codecvt.virtuals"> [lib.locale.codecvt.virtuals]</a> paragraph 2:</p>
|
|
|
|
<blockquote>
|
|
<p>A <tt>codecvt</tt> facet that is used by <tt>basic_filebuf</tt>
|
|
(27.8 <a href="lib-iostreams.html#lib.file.streams"> [lib.file.streams]</a>) must have the property that if</p>
|
|
<pre>
|
|
do_out(state, from, from_end, from_next, to, to_lim, to_next)
|
|
</pre>
|
|
would return <tt>ok</tt>, where <tt>from != from_end</tt>, then
|
|
<pre>
|
|
do_out(state, from, from + 1, from_next, to, to_end, to_next)
|
|
</pre>
|
|
must also return <tt>ok</tt>, and that if
|
|
<pre>
|
|
do_in(state, from, from_end, from_next, to, to_lim, to_next)
|
|
</pre>
|
|
would return <tt>ok</tt>, where <tt>to != to_lim</tt>, then
|
|
<pre>
|
|
do_in(state, from, from_end, from_next, to, to + 1, to_next)
|
|
</pre>
|
|
<p>must also return <tt>ok</tt>. [<i>Footnote:</i> Informally, this
|
|
means that <tt>basic_filebuf</tt> assumes that the mapping from
|
|
internal to external characters is 1 to N: a <tt>codecvt</tt> that is
|
|
used by <tt>basic_filebuf</tt> must be able to translate characters
|
|
one internal character at a time. <i>--End Footnote</i>]</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Redmond: Minor change in proposed resolution. Original
|
|
proposed resolution talked about "success", with a parenthetical
|
|
comment that success meant returning <tt>ok</tt>. New wording
|
|
removes all talk about "success", and just talks about the
|
|
return value.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
|
|
<p>The proposed resoluion says that conversions can be performed one
|
|
internal character at a time. This rules out some encodings that
|
|
would otherwise be legal. The alternative answer would mean there
|
|
would be some internal positions that do not correspond to any
|
|
external file position.</p>
|
|
<p>
|
|
An example of an encoding that this rules out is one where the
|
|
<tt>internT</tt> and <tt>externT</tt> are of the same type, and
|
|
where the internal sequence <tt>c1 c2</tt> corresponds to the
|
|
external sequence <tt>c2 c1</tt>.
|
|
</p>
|
|
<p>It was generally agreed that <tt>basic_filebuf</tt> relies
|
|
on this property: it was designed under the assumption that
|
|
the external-to-internal mapping is N-to-1, and it is not clear
|
|
that <tt>basic_filebuf</tt> is implementable without that
|
|
restriction.
|
|
</p>
|
|
<p>
|
|
The proposed resolution is expressed as a restriction on
|
|
<tt>codecvt</tt> when used by <tt>basic_filebuf</tt>, rather
|
|
than a blanket restriction on all <tt>codecvt</tt> facets,
|
|
because <tt>basic_filebuf</tt> is the only other part of the
|
|
library that uses <tt>codecvt</tt>. If a user wants to define
|
|
a <tt>codecvt</tt> facet that implements a more general N-to-M
|
|
mapping, there is no reason to prohibit it, so long as the user
|
|
does not expect <tt>basic_filebuf</tt> to be able to use it.
|
|
</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#Review">Review</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><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>
|
|
|
|
<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><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. (A) Users may not
|
|
explicitly instantiate standard library templates, except on
|
|
user-defined types. Consequence: library implementors may freely
|
|
specialize or instantiate templates. (B) 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. (C) Users may
|
|
explicitly instantiate any standard library template.
|
|
]</i></p>
|
|
|
|
<p><i>[Straw poll (first number is favor, second is strongly oppose):
|
|
A - 4, 0; B - 0, 9; C - 9, 1. Proposed resolution 1, above, is
|
|
option A. (It is the original proposed resolution.) Proposed
|
|
resolution 2, above, is option C. Because there was no support
|
|
for option B, no wording is provided.]</i></p>
|
|
|
|
<p><i>[Redmond: discussed again; straw poll had results similar to
|
|
those of Copenhagen (A - 1, 3; B - 6, 2; C - 8, 4). Most people said
|
|
they could live with any option. The only objection to option A is
|
|
potential implementation difficulty. Steve Clamage volunteered do a
|
|
survey to see if there are any popular platforms where option A would
|
|
present a real problem for implementors. See his reflector message,
|
|
c++std-lib-9002.
|
|
]</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#Review">Review</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#Review">Review</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="198"><h3>198. Validity of pointers and references unspecified after iterator destruction</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#Ready">Ready</a> <b>Submitter:</b> Beman Dawes <b>Date:</b> 3 Nov 1999</p>
|
|
<p>
|
|
Is a pointer or reference obtained from an iterator still valid after
|
|
destruction of the iterator?
|
|
</p>
|
|
<p>
|
|
Is a pointer or reference obtained from an iterator still valid after the value
|
|
of the iterator changes?
|
|
</p>
|
|
<blockquote>
|
|
<pre>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <iterator>
|
|
|
|
int main()
|
|
{
|
|
typedef std::vector<int> vec_t;
|
|
vec_t v;
|
|
v.push_back( 1 );
|
|
|
|
// Is a pointer or reference obtained from an iterator still
|
|
// valid after destruction of the iterator?
|
|
int * p = &*v.begin();
|
|
std::cout << *p << '\n'; // OK?
|
|
|
|
// Is a pointer or reference obtained from an iterator still
|
|
// valid after the value of the iterator changes?
|
|
vec_t::iterator iter( v.begin() );
|
|
p = &*iter++;
|
|
std::cout << *p << '\n'; // OK?
|
|
|
|
return 0;
|
|
}
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<p>The standard doesn't appear to directly address these
|
|
questions. The standard needs to be clarified. At least two real-world
|
|
cases have been reported where library implementors wasted
|
|
considerable effort because of the lack of clarity in the
|
|
standard. The question is important because requiring pointers and
|
|
references to remain valid has the effect for practical purposes of
|
|
prohibiting iterators from pointing to cached rather than actual
|
|
elements of containers.</p>
|
|
|
|
<p>The standard itself assumes that pointers and references obtained
|
|
from an iterator are still valid after iterator destruction or
|
|
change. The definition of reverse_iterator::operator*(), 24.4.1.3.3 <a href="lib-iterators.html#lib.reverse.iter.op.star"> [lib.reverse.iter.op.star]</a>, which returns a reference, defines
|
|
effects:</p>
|
|
|
|
<blockquote>
|
|
<pre>Iterator tmp = current;
|
|
return *--tmp;</pre>
|
|
</blockquote>
|
|
<p>The definition of reverse_iterator::operator->(), 24.4.1.3.4 <a href="lib-iterators.html#lib.reverse.iter.opref"> [lib.reverse.iter.opref]</a>, which returns a pointer, defines effects:</p>
|
|
<blockquote>
|
|
<pre>return &(operator*());</pre>
|
|
</blockquote>
|
|
|
|
<p>Because the standard itself assumes pointers and references remain
|
|
valid after iterator destruction or change, the standard should say so
|
|
explicitly. This will also reduce the chance of user code breaking
|
|
unexpectedly when porting to a different standard library
|
|
implementation.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Add a new paragraph to 24.1 <a href="lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a>:</p>
|
|
<blockquote>
|
|
Destruction of an iterator may invalidate pointers and references
|
|
previously obtained from that iterator.
|
|
</blockquote>
|
|
|
|
<p>Replace paragraph 1 of 24.4.1.3.3 <a href="lib-iterators.html#lib.reverse.iter.op.star"> [lib.reverse.iter.op.star]</a> with:</p>
|
|
|
|
<blockquote>
|
|
<p><b>Effects:</b></p>
|
|
<pre>
|
|
this->tmp = current;
|
|
--this->tmp;
|
|
return *this->tmp;
|
|
</pre>
|
|
|
|
<p>
|
|
[<i>Note:</i> This operation must use an auxiliary member variable,
|
|
rather than a temporary variable, to avoid returning a reference that
|
|
persists beyond the lifetime of its associated iterator. (See
|
|
24.1 <a href="lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a>.) The name of this member variable is shown for
|
|
exposition only. <i>--end note</i>]
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Post-Tokyo: The issue has been reformulated purely
|
|
in terms of iterators.]</i></p>
|
|
|
|
<p><i>[Pre-Toronto: Steve Cleary pointed out the no-invalidation
|
|
assumption by reverse_iterator. The issue and proposed resolution was
|
|
reformulated yet again to reflect this reality.]</i></p>
|
|
|
|
<p><i>[Copenhagen: Steve Cleary pointed out that reverse_iterator
|
|
assumes its underlying iterator has persistent pointers and
|
|
references. Andy Koenig pointed out that it is possible to rewrite
|
|
reverse_iterator so that it no longer makes such an assupmption.
|
|
However, this issue is related to issue <a href="lwg-active.html#299">299</a>. If we
|
|
decide it is intentional that <tt>p[n]</tt> may return by value
|
|
instead of reference when <tt>p</tt> is a Random Access Iterator,
|
|
other changes in reverse_iterator will be necessary.]</i></p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>This issue has been discussed extensively. Note that it is
|
|
<i>not</i> an issue about the behavior of predefined iterators. It is
|
|
asking whether or not user-defined iterators are permitted to have
|
|
transient pointers and references. Several people presented examples
|
|
of useful user-defined iterators that have such a property; examples
|
|
include a B-tree iterator, and an "iota iterator" that doesn't point
|
|
to memory. Library implementors already seem to be able to cope with
|
|
such iterators: they take pains to avoid forming references to memory
|
|
that gets iterated past. The only place where this is a problem is
|
|
<tt>reverse_iterator</tt>, so this issue changes
|
|
<tt>reverse_iterator</tt> to make it work.</p>
|
|
|
|
<p>This resolution does not weaken any guarantees provided by
|
|
predefined iterators like <tt>list<int>::iterator</tt>.
|
|
Clause 23 should be reviewed to make sure that guarantees for
|
|
predefined iterators are as strong as users expect.</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#Review">Review</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#Review">Review</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, 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><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#Open">Open</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>
|
|
<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#Open">Open</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><b>Proposed resolution:</b></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>
|
|
|
|
<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#Open">Open</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>
|
|
<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#Ready">Ready</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>
|
|
In 22.2.2.2.2 <a href="lib-locales.html#lib.facet.num.put.virtuals"> [lib.facet.num.put.virtuals]</a>, paragraph 11, change
|
|
"if <tt>(flags & fixed) != 0</tt>" to
|
|
"if <tt>(flags & floatfield) == fixed ||
|
|
(flags & floatfield) == scientific</tt>"
|
|
</p>
|
|
<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 %e.</p>
|
|
<p>Turning to the C standard, a precision of 0 is meaningful
|
|
for %f and %e, but not for %g: for %g, precision 0 is taken
|
|
to be the same as precision 1.</p>
|
|
<p>The proposed resolution has the effect that the output of
|
|
the above program will be "1e+00".</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#Review">Review</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. There was some support for an alternative resolution: we check
|
|
on both sides of the hint (both before and after, in that order). If
|
|
either is the correct location, the hint is used; otherwise it is not.
|
|
This would be different from the original proposed resolution, because
|
|
in the proposed resolution the hint will be used even if it is very
|
|
far from the insertion point. JC van Winkel supplied precise wording
|
|
for both options.]</i></p>
|
|
|
|
<p><i>[Copenhagen: the LWG looked at both options, and preferred the
|
|
original. This preference is contingent on seeing a reference
|
|
implementation showing that it is possible to implement this
|
|
requirement without loss of efficiency.]</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>
|
|
|
|
<hr>
|
|
<a name="239"><h3>239. Complexity of unique() and/or unique_copy incorrect</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#Review">Review</a> <b>Submitter:</b> Angelika Langer <b>Date:</b> May 15 2000</p>
|
|
<p>The complexity of unique and unique_copy are inconsistent with each
|
|
other and inconsistent with the implementations. The standard
|
|
specifies:</p>
|
|
|
|
<p>for unique():</p>
|
|
|
|
<blockquote>-3- Complexity: If the range (last - first) is not empty, exactly
|
|
(last - first) - 1 applications of the corresponding predicate, otherwise
|
|
no applications of the predicate.</blockquote>
|
|
|
|
<p>for unique_copy():</p>
|
|
|
|
<blockquote>-7- Complexity: Exactly last - first applications of the corresponding
|
|
predicate.</blockquote>
|
|
|
|
<p>
|
|
The implementations do it the other way round: unique() applies the
|
|
predicate last-first times and unique_copy() applies it last-first-1
|
|
times.</p>
|
|
|
|
<p>As both algorithms use the predicate for pair-wise comparison of
|
|
sequence elements I don't see a justification for unique_copy()
|
|
applying the predicate last-first times, especially since it is not
|
|
specified to which pair in the sequence the predicate is applied
|
|
twice.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change both complexity sections in 25.2.8 <a href="lib-algorithms.html#lib.alg.unique"> [lib.alg.unique]</a> to:</p>
|
|
|
|
<blockquote>Complexity: For nonempty ranges, exactly last - first - 1
|
|
applications of the corresponding predicate.</blockquote>
|
|
|
|
<hr>
|
|
<a name="240"><h3>240. Complexity of adjacent_find() is meaningless</h3></a><p>
|
|
<b>Section:</b> 25.1.5 <a href="lib-algorithms.html#lib.alg.adjacent.find"> [lib.alg.adjacent.find]</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>The complexity section of adjacent_find is defective:</p>
|
|
|
|
<blockquote>
|
|
<pre>
|
|
template <class ForwardIterator>
|
|
ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last
|
|
BinaryPredicate pred);
|
|
</pre>
|
|
|
|
<p>-1- Returns: The first iterator i such that both i and i + 1 are in
|
|
the range [first, last) for which the following corresponding
|
|
conditions hold: *i == *(i + 1), pred(*i, *(i + 1)) != false. Returns
|
|
last if no such iterator is found.</p>
|
|
|
|
<p>-2- Complexity: Exactly find(first, last, value) - first applications
|
|
of the corresponding predicate.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>In the Complexity section, it is not defined what "value"
|
|
is supposed to mean. My best guess is that "value" means an
|
|
object for which one of the conditions pred(*i,value) or
|
|
pred(value,*i) is true, where i is the iterator defined in the Returns
|
|
section. However, the value type of the input sequence need not be
|
|
equality-comparable and for this reason the term find(first, last,
|
|
value) - first is meaningless.</p>
|
|
|
|
<p>A term such as find_if(first, last, bind2nd(pred,*i)) - first or
|
|
find_if(first, last, bind1st(pred,*i)) - first might come closer to
|
|
the intended specification. Binders can only be applied to function
|
|
objects that have the function call operator declared const, which is
|
|
not required of predicates because they can have non-const data
|
|
members. For this reason, a specification using a binder could only be
|
|
an "as-if" specification.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the complexity section in 25.1.5 <a href="lib-algorithms.html#lib.alg.adjacent.find"> [lib.alg.adjacent.find]</a> to:</p>
|
|
<blockquote>
|
|
For a nonempty range, exactly <tt>min((<i>i</i> - <i>first</i>) + 1,
|
|
(<i>last</i> - <i>first</i>) - 1)</tt> applications of the
|
|
corresponding predicate, where <i>i</i> is <tt>adjacent_find</tt>'s
|
|
return value.
|
|
</blockquote>
|
|
|
|
<p><i>[Copenhagen: the original resolution specified an upper
|
|
bound. The LWG preferred an exact count.]</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#Review">Review</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>
|
|
-4- Requires: The ranges [first, last) and [result, result+(last-first))
|
|
shall not overlap. The expression *result = *first must be valid. If
|
|
both InputIterator and OutputIterator do not meet the requirements of
|
|
forward iterator then the value type of InputIterator must be copy
|
|
constructible. Otherwise copy constructible is not required.
|
|
</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>
|
|
|
|
<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#Review">Review</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.</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><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. A small group
|
|
(Herb, Kevlin, Howard, Martin, Dave) will try to make a
|
|
recommendation.]</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="270"><h3>270. Binary search requirements overly strict</h3></a><p>
|
|
<b>Section:</b> 25.3.3 <a href="lib-algorithms.html#lib.alg.binary.search"> [lib.alg.binary.search]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 18 Oct 2000</p>
|
|
<p>
|
|
Each of the four binary search algorithms (lower_bound, upper_bound,
|
|
equal_range, binary_search) has a form that allows the user to pass a
|
|
comparison function object. According to 25.3, paragraph 2, that
|
|
comparison function object has to be a strict weak ordering.
|
|
</p>
|
|
|
|
<p>
|
|
This requirement is slightly too strict. Suppose we are searching
|
|
through a sequence containing objects of type X, where X is some
|
|
large record with an integer key. We might reasonably want to look
|
|
up a record by key, in which case we would want to write something
|
|
like this:
|
|
</p>
|
|
<pre>
|
|
struct key_comp {
|
|
bool operator()(const X& x, int n) const {
|
|
return x.key() < n;
|
|
}
|
|
}
|
|
|
|
std::lower_bound(first, last, 47, key_comp());
|
|
</pre>
|
|
|
|
<p>
|
|
key_comp is not a strict weak ordering, but there is no reason to
|
|
prohibit its use in lower_bound.
|
|
</p>
|
|
|
|
<p>
|
|
There's no difficulty in implementing lower_bound so that it allows
|
|
the use of something like key_comp. (It will probably work unless an
|
|
implementor takes special pains to forbid it.) What's difficult is
|
|
formulating language in the standard to specify what kind of
|
|
comparison function is acceptable. We need a notion that's slightly
|
|
more general than that of a strict weak ordering, one that can encompass
|
|
a comparison function that involves different types. Expressing that
|
|
notion may be complicated.
|
|
</p>
|
|
|
|
<p><i>Additional questions raised at the Toronto meeting:</i></p>
|
|
<ul>
|
|
<li> Do we really want to specify what ordering the implementor must
|
|
use when calling the function object? The standard gives
|
|
specific expressions when describing these algorithms, but it also
|
|
says that other expressions (with different argument order) are
|
|
equivalent.</li>
|
|
<li> If we are specifying ordering, note that the standard uses both
|
|
orderings when describing <tt>equal_range</tt>.</li>
|
|
<li> Are we talking about requiring these algorithms to work properly
|
|
when passed a binary function object whose two argument types
|
|
are not the same, or are we talking about requirements when
|
|
they are passed a binary function object with several overloaded
|
|
versions of <tt>operator()</tt>?</li>
|
|
<li> The definition of a strict weak ordering does not appear to give
|
|
any guidance on issues of overloading; it only discusses expressions,
|
|
and all of the values in these expressions are of the same type.
|
|
Some clarification would seem to be in order.</li>
|
|
</ul>
|
|
|
|
<p><i>Additional discussion from Copenhagen:</i></p>
|
|
<ul>
|
|
<li>It was generally agreed that there is a real defect here: if
|
|
the predicate is merely required to be a Strict Weak Ordering, then
|
|
it's possible to pass in a function object with an overloaded
|
|
operator(), where the version that's actually called does something
|
|
completely inappropriate. (Such as returning a random value.)</li>
|
|
|
|
<li>An alternative formulation was presented in a paper distributed by
|
|
David Abrahams at the meeting, "Binary Search with Heterogeneous
|
|
Comparison", J16-01/0027 = WG21 N1313: Instead of viewing the
|
|
predicate as a Strict Weak Ordering acting on a sorted sequence, view
|
|
the predicate/value pair as something that partitions a sequence.
|
|
This is almost equivalent to saying that we should view binary search
|
|
as if we are given a unary predicate and a sequence, such that f(*p)
|
|
is true for all p below a specific point and false for all p above it.
|
|
The proposed resolution is based on that alternative formulation.</li>
|
|
</ul>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>Change 25.3 [lib.alg.sorting] paragraph 3 from:</p>
|
|
|
|
<blockquote>
|
|
3 For all algorithms that take Compare, there is a version that uses
|
|
operator< instead. That is, comp(*i, *j) != false defaults to *i <
|
|
*j != false. For the algorithms to work correctly, comp has to
|
|
induce a strict weak ordering on the values.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
3 For all algorithms that take Compare, there is a version that uses
|
|
operator< instead. That is, comp(*i, *j) != false defaults to *i
|
|
< *j != false. For algorithms other than those described in
|
|
lib.alg.binary.search (25.3.3) to work correctly, comp has to induce
|
|
a strict weak ordering on the values.
|
|
</blockquote>
|
|
|
|
<p>Add the following paragraph after 25.3 [lib.alg.sorting] paragraph 5:</p>
|
|
|
|
<blockquote>
|
|
-6- A sequence [start, finish) is partitioned with respect to an
|
|
expression f(e) if there exists an integer n such that
|
|
for all 0 <= i < distance(start, finish), f(*(begin+i)) is true if
|
|
and only if i < n.
|
|
</blockquote>
|
|
|
|
<p>Change 25.3.3 [lib.alg.binary.search] paragraph 1 from:</p>
|
|
|
|
<blockquote>
|
|
-1- All of the algorithms in this section are versions of binary
|
|
search and assume that the sequence being searched is in order
|
|
according to the implied or explicit comparison function. They work
|
|
on non-random access iterators minimizing the number of
|
|
comparisons, which will be logarithmic for all types of
|
|
iterators. They are especially appropriate for random access
|
|
iterators, because these algorithms do a logarithmic number of
|
|
steps through the data structure. For non-random access iterators
|
|
they execute a linear number of steps.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-1- All of the algorithms in this section are versions of binary
|
|
search and assume that the sequence being searched is partitioned
|
|
with respect to an expression formed by binding the search key to
|
|
an argument of the implied or explicit comparison function. They
|
|
work on non-random access iterators minimizing the number of
|
|
comparisons, which will be logarithmic for all types of
|
|
iterators. They are especially appropriate for random access
|
|
iterators, because these algorithms do a logarithmic number of
|
|
steps through the data structure. For non-random access iterators
|
|
they execute a linear number of steps.
|
|
</blockquote>
|
|
|
|
<p>Change 25.3.3.1 [lib.lower.bound] paragraph 1 from:</p>
|
|
|
|
<blockquote>
|
|
-1- Requires: Type T is LessThanComparable
|
|
(lib.lessthancomparable).
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-1- Requires: The elements e of [first, last) are partitioned with
|
|
respect to the expression e < value or comp(e, value)
|
|
</blockquote>
|
|
|
|
|
|
<p>Remove 25.3.3.1 [lib.lower.bound] paragraph 2:</p>
|
|
|
|
<blockquote>
|
|
-2- Effects: Finds the first position into which value can be
|
|
inserted without violating the ordering.
|
|
</blockquote>
|
|
|
|
<p>Change 25.3.3.2 [lib.upper.bound] paragraph 1 from:</p>
|
|
|
|
<blockquote>
|
|
-1- Requires: Type T is LessThanComparable (lib.lessthancomparable).
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-1- Requires: The elements e of [first, last) are partitioned with
|
|
respect to the expression !(value < e) or !comp(value, e)
|
|
</blockquote>
|
|
|
|
<p>Remove 25.3.3.2 [lib.upper.bound] paragraph 2:</p>
|
|
|
|
<blockquote>
|
|
-2- Effects: Finds the furthermost position into which value can be
|
|
inserted without violating the ordering.
|
|
</blockquote>
|
|
|
|
<p>Change 25.3.3.3 [lib.equal.range] paragraph 1 from:</p>
|
|
|
|
<blockquote>
|
|
-1- Requires: Type T is LessThanComparable
|
|
(lib.lessthancomparable).
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-1- Requires: The elements e of [first, last) are partitioned with
|
|
respect to the expressions e < value and !(value < e) or
|
|
comp(e, value) and !comp(value, e). Also, for all elements e of
|
|
[first, last), e < value implies !(value < e) or comp(e,
|
|
value) implies !comp(value, e)
|
|
</blockquote>
|
|
|
|
<p>Change 25.3.3.3 [lib.equal.range] paragraph 2 from:</p>
|
|
|
|
<blockquote>
|
|
-2- Effects: Finds the largest subrange [i, j) such that the value
|
|
can be inserted at any iterator k in it without violating the
|
|
ordering. k satisfies the corresponding conditions: !(*k < value)
|
|
&& !(value < *k) or comp(*k, value) == false && comp(value, *k) ==
|
|
false.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<pre>
|
|
-2- Returns:
|
|
make_pair(lower_bound(first, last, value),
|
|
upper_bound(first, last, value))
|
|
or
|
|
make_pair(lower_bound(first, last, value, comp),
|
|
upper_bound(first, last, value, comp))
|
|
</pre>
|
|
|
|
<p>Change 25.3.3.3 [lib.binary.search] paragraph 1 from:</p>
|
|
|
|
<blockquote>
|
|
-1- Requires: Type T is LessThanComparable
|
|
(lib.lessthancomparable).
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-1- Requires: The elements e of [first, last) are partitioned with
|
|
respect to the expressions e < value and !(value < e) or comp(e,
|
|
value) and !comp(value, e). Also, for all elements e of [first,
|
|
last), e < value implies !(value < e) or comp(e, value) implies
|
|
!comp(value, e)
|
|
</blockquote>
|
|
|
|
<p><i>[Copenhagen: Dave Abrahams provided this wording]</i></p>
|
|
|
|
<p><i>[Redmond: Minor changes in wording. (Removed "non-negative", and
|
|
changed the "other than those described in" wording.) Also, the LWG
|
|
decided to accept the "optional" part.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>The proposed resolution reinterprets binary search. Instead of
|
|
thinking about searching for a value in a sorted range, we view that
|
|
as an important special case of a more general algorithm: searching
|
|
for the partition point in a partitioned range.</p>
|
|
|
|
<p>We also add a guarantee that the old wording did not: we ensure
|
|
that the upper bound is no earlier than the lower bound, that
|
|
the pair returned by equal_range is a valid range, and that the first
|
|
part of that pair is the lower bound.</p>
|
|
<hr>
|
|
<a name="274"><h3>274. a missing/impossible 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#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 02 Nov 2000</p>
|
|
<p>
|
|
I see that table 31 in 20.1.5, p3 allows T in std::allocator<T> to be of
|
|
any type. But the synopsis in 20.4.1 calls for allocator<>::address() to
|
|
be overloaded on reference and const_reference, which is ill-formed for
|
|
all T = const U. In other words, this won't work:
|
|
</p>
|
|
|
|
<p>
|
|
template class std::allocator<const int>;
|
|
</p>
|
|
|
|
<p>
|
|
The obvious solution is to disallow specializations of allocators on
|
|
const types. However, while containers' elements are required to be
|
|
assignable (which rules out specializations on const T's), I think that
|
|
allocators might perhaps be potentially useful for const values in other
|
|
contexts. So if allocators are to allow const types a partial
|
|
specialization of std::allocator<const T> would probably have to be
|
|
provided.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the text in row 1, column 2 of table 32 in 20.1.5, p3 from</p>
|
|
|
|
<blockquote>
|
|
any type
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
<blockquote>
|
|
any non-const, non-reference type
|
|
</blockquote>
|
|
|
|
<p><i>[Redmond: previous proposed resolution was "any non-const,
|
|
non-volatile, non-reference type". Got rid of the "non-volatile".]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
Two resolutions were originally proposed: one that partially
|
|
specialized std::allocator for const types, and one that said an
|
|
allocator's value type may not be const. The LWG chose the second.
|
|
The first wouldn't be appropriate, because allocators are intended for
|
|
use by containers, and const value types don't work in containers.
|
|
Encouraging the use of allocators with const value types would only
|
|
lead to unsafe code.
|
|
</p>
|
|
<p>
|
|
The original text for proposed resolution 2 was modified so that it
|
|
also forbids volatile types and reference types.
|
|
</p>
|
|
<hr>
|
|
<a name="276"><h3>276. Assignable requirement for container value type overly strict</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> Peter Dimov <b>Date:</b> 07 Nov 2000</p>
|
|
<p>
|
|
23.1/3 states that the objects stored in a container must be
|
|
Assignable. 23.3.1 <a href="lib-containers.html#lib.map"> [lib.map]</a>, paragraph 2,
|
|
states that map satisfies all requirements for a container, while in
|
|
the same time defining value_type as pair<const Key, T> - a type
|
|
that is not Assignable.
|
|
</p>
|
|
|
|
<p>
|
|
It should be noted that there exists a valid and non-contradictory
|
|
interpretation of the current text. The wording in 23.1/3 avoids
|
|
mentioning value_type, referring instead to "objects stored in a
|
|
container." One might argue that map does not store objects of
|
|
type map::value_type, but of map::mapped_type instead, and that the
|
|
Assignable requirement applies to map::mapped_type, not
|
|
map::value_type.
|
|
</p>
|
|
|
|
<p>
|
|
However, this makes map a special case (other containers store objects of
|
|
type value_type) and the Assignable requirement is needlessly restrictive in
|
|
general.
|
|
</p>
|
|
|
|
<p>
|
|
For example, the proposed resolution of active library issue
|
|
<a href="lwg-defects.html#103">103</a> is to make set::iterator a constant iterator; this
|
|
means that no set operations can exploit the fact that the stored
|
|
objects are Assignable.
|
|
</p>
|
|
|
|
<p>
|
|
This is related to, but slightly broader than, closed issue
|
|
<a href="lwg-closed.html#140">140</a>.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>23.1/3: Strike the trailing part of the sentence:</p>
|
|
<blockquote>
|
|
, and the additional requirements of Assignable types from 23.1/3
|
|
</blockquote>
|
|
<p>so that it reads:</p>
|
|
<blockquote>
|
|
-3- The type of objects stored in these components must meet the
|
|
requirements of CopyConstructible types (lib.copyconstructible).
|
|
</blockquote>
|
|
|
|
<p>23.1/4: Modify to make clear that this requirement is not for all
|
|
containers. Change to:</p>
|
|
|
|
<blockquote>
|
|
-4- Table 64 defines the Assignable requirement. Some containers
|
|
require this property of the types to be stored in the container. T is
|
|
the type used to instantiate the container. t is a value of T, and u is
|
|
a value of (possibly const) T.
|
|
</blockquote>
|
|
|
|
<p>23.1, Table 65: in the first row, change "T is Assignable" to "T is
|
|
CopyConstructible".</p>
|
|
|
|
<p>23.2.1/2: Add sentence for Assignable requirement. Change to:</p>
|
|
|
|
<blockquote>
|
|
-2- A deque satisfies all of the requirements of a container and of a
|
|
reversible container (given in tables in lib.container.requirements) and
|
|
of a sequence, including the optional sequence requirements
|
|
(lib.sequence.reqmts). In addition to the requirements on the stored
|
|
object described in 23.1[lib.container.requirements], the stored object
|
|
must also meet the requirements of Assignable. Descriptions are
|
|
provided here only for operations on deque that are not described in one
|
|
of these tables or for operations where there is additional semantic
|
|
information.
|
|
</blockquote>
|
|
|
|
<p>23.2.2/2: Add Assignable requirement to specific methods of list.
|
|
Change to:</p>
|
|
|
|
<blockquote>
|
|
<p>-2- A list satisfies all of the requirements of a container and of a
|
|
reversible container (given in two tables in lib.container.requirements)
|
|
and of a sequence, including most of the the optional sequence
|
|
requirements (lib.sequence.reqmts). The exceptions are the operator[]
|
|
and at member functions, which are not provided.
|
|
|
|
[Footnote: These member functions are only provided by containers whose
|
|
iterators are random access iterators. --- end foonote]
|
|
</p>
|
|
|
|
<p>list does not require the stored type T to be Assignable unless the
|
|
following methods are instantiated:
|
|
|
|
[Footnote: Implementors are permitted but not required to take advantage
|
|
of T's Assignable properties for these methods. -- end foonote]
|
|
</p>
|
|
<pre>
|
|
list<T,Allocator>& operator=(const list<T,Allocator>& x );
|
|
template <class InputIterator>
|
|
void assign(InputIterator first, InputIterator last);
|
|
void assign(size_type n, const T& t);
|
|
</pre>
|
|
|
|
|
|
<p>Descriptions are provided here only for operations on list that are not
|
|
described in one of these tables or for operations where there is
|
|
additional semantic information.</p>
|
|
</blockquote>
|
|
|
|
<p>23.2.4/2: Add sentence for Assignable requirement. Change to:</p>
|
|
|
|
<blockquote>
|
|
-2- A vector satisfies all of the requirements of a container and of a
|
|
reversible container (given in two tables in lib.container.requirements)
|
|
and of a sequence, including most of the optional sequence requirements
|
|
(lib.sequence.reqmts). The exceptions are the push_front and pop_front
|
|
member functions, which are not provided. In addition to the
|
|
requirements on the stored object described in
|
|
23.1[lib.container.requirements], the stored object must also meet the
|
|
requirements of Assignable. Descriptions are provided here only for
|
|
operations on vector that are not described in one of these tables or
|
|
for operations where there is additional semantic information.
|
|
</blockquote>
|
|
<p><b>Rationale:</b></p>
|
|
<p>list, set, multiset, map, multimap are able to store non-Assignables.
|
|
However, there is some concern about <tt>list<T></tt>:
|
|
although in general there's no reason for T to be Assignable, some
|
|
implementations of the member functions <tt>operator=</tt> and
|
|
<tt>assign</tt> do rely on that requirement. The LWG does not want
|
|
to forbid such implementations.</p>
|
|
|
|
<p>Note that the type stored in a standard container must still satisfy
|
|
the requirements of the container's allocator; this rules out, for
|
|
example, such types as "const int". See issue <a href="lwg-active.html#274">274</a>
|
|
for more details.
|
|
</p>
|
|
|
|
<p>In principle we could also relax the "Assignable" requirement for
|
|
individual <tt>vector</tt> member functions, such as
|
|
<tt>push_back</tt>. However, the LWG did not see great value in such
|
|
selective relaxation. Doing so would remove implementors' freedom to
|
|
implement <tt>vector::push_back</tt> in terms of
|
|
<tt>vector::insert</tt>.</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#Review">Review</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>
|
|
|
|
<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#Open">Open</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>
|
|
|
|
<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#Review">Review</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>
|
|
|
|
<hr>
|
|
<a name="284"><h3>284. unportable example in 20.3.7, p6</h3></a><p>
|
|
<b>Section:</b> 20.3.7 <a href="lib-utilities.html#lib.function.pointer.adaptors"> [lib.function.pointer.adaptors]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 26 Dec 2000</p>
|
|
<p>The example in 20.3.7 <a href="lib-utilities.html#lib.function.pointer.adaptors"> [lib.function.pointer.adaptors]</a>, p6 shows how to use the C
|
|
library function <tt>strcmp()</tt> with the function pointer adapter
|
|
<tt>ptr_fun()</tt>. But since it's unspecified whether the C library
|
|
functions have <tt>extern "C"</tt> or <tt>extern
|
|
"C++"</tt> linkage [17.4.2.2 <a href="lib-intro.html#lib.using.linkage"> [lib.using.linkage]</a>], and since
|
|
function pointers with different the language linkage specifications
|
|
(7.5 <a href="dcl.html#dcl.link"> [dcl.link]</a>) are incompatible, whether this example is
|
|
well-formed is unspecified.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 20.3.7 <a href="lib-utilities.html#lib.function.pointer.adaptors"> [lib.function.pointer.adaptors]</a> paragraph 6 from:</p>
|
|
<blockquote>
|
|
<p>[<i>Example:</i>
|
|
</p>
|
|
<pre>
|
|
replace_if(v.begin(), v.end(), not1(bind2nd(ptr_fun(strcmp), "C")), "C++");
|
|
</pre>
|
|
<p>replaces each <tt>C</tt> with <tt>C++</tt> in sequence <tt>v</tt>.</p>
|
|
</blockquote>
|
|
|
|
|
|
<p>to:</p>
|
|
<blockquote>
|
|
<p>[<i>Example:</i>
|
|
</p>
|
|
<pre>
|
|
int compare(const char*, const char*);
|
|
replace_if(v.begin(), v.end(),
|
|
not1(bind2nd(ptr_fun(compare), "abc")), "def");
|
|
</pre>
|
|
<p>replaces each <tt>abc</tt> with <tt>def</tt> in sequence <tt>v</tt>.</p>
|
|
</blockquote>
|
|
|
|
<p>Also, remove footnote 215 in that same paragraph.</p>
|
|
|
|
<p><i>[Copenhagen: Minor change in the proposed resolution. Since this
|
|
issue deals in part with C and C++ linkage, it was believed to be too
|
|
confusing for the strings in the example to be "C" and "C++".
|
|
]</i></p>
|
|
|
|
<p><i>[Redmond: More minor changes. Got rid of the footnote (which
|
|
seems to make a sweeping normative requirement, even though footnotes
|
|
aren't normative), and changed the sentence after the footnote so that
|
|
it corresponds to the new code fragment.]</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#Open">Open</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><i>[The LWG agrees that the standard should answer these questions.
|
|
Matt will provide wording.]</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>
|
|
|
|
<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>
|
|
Change 23.2.2.4, p23 to:
|
|
</p>
|
|
<blockquote>
|
|
<b>Effects</b>: If &x == this, does nothing; otherwise, merges the
|
|
argument list into the list.
|
|
</blockquote>
|
|
|
|
<p><i>[Copenhagen: The proposed resolution does 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>
|
|
|
|
<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#Review">Review</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 Shift-JIS, for
|
|
example, and it would rule out a fixed-width encoding of UCS-4.</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="310"><h3>310. Is errno a macro?</h3></a><p>
|
|
<b>Section:</b> 17.4.1.2 <a href="lib-intro.html#lib.headers"> [lib.headers]</a>, 19.3 <a href="lib-diagnostics.html#lib.errno"> [lib.errno]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Steve Clamage <b>Date:</b> 21 Mar 2001</p>
|
|
<p>
|
|
Exactly how should errno be declared in a conforming C++ header?
|
|
</p>
|
|
|
|
<p>
|
|
The C standard says in 7.1.4 that it is unspecified whether errno is a
|
|
macro or an identifier with external linkage. In some implementations
|
|
it can be either, depending on compile-time options. (E.g., on
|
|
Solaris in multi-threading mode, errno is a macro that expands to a
|
|
function call, but is an extern int otherwise. "Unspecified" allows
|
|
such variability.)
|
|
</p>
|
|
|
|
<p>The C++ standard:</p>
|
|
<ul>
|
|
<li>17.4.1.2 says in a note that errno must be macro in C. (false)</li>
|
|
<li>17.4.3.1.3 footnote 166 says errno is reserved as an external
|
|
name (true), and implies that it is an identifier.</li>
|
|
<li>19.3 simply lists errno as a macro (by what reasoning?) and goes
|
|
on to say that the contents of of C++ <errno.h> are the
|
|
same as in C, begging the question.</li>
|
|
<li>C.2, table 95 lists errno as a macro, without comment.</li>
|
|
</ul>
|
|
|
|
<p>I find no other references to errno.</p>
|
|
|
|
<p>We should either explicitly say that errno must be a macro, even
|
|
though it need not be a macro in C, or else explicitly leave it
|
|
unspecified. We also need to say something about namespace std.
|
|
A user who includes <cerrno> needs to know whether to write
|
|
<tt>errno</tt>, or <tt>::errno</tt>, or <tt>std::errno</tt>, or
|
|
else <cerrno> is useless.</p>
|
|
|
|
<p>Two acceptable fixes:</p>
|
|
<ul>
|
|
<li><p>errno must be a macro. This is trivially satisfied by adding<br>
|
|
#define errno (::std::errno)<br>
|
|
to the headers if errno is not already a macro. You then always
|
|
write errno without any scope qualification, and it always expands
|
|
to a correct reference. Since it is always a macro, you know to
|
|
avoid using errno as a local identifer.</p></li>
|
|
<li><p>errno is in the global namespace. This fix is inferior, because
|
|
::errno is not guaranteed to be well-formed.</p></li>
|
|
</ul>
|
|
|
|
<p><i>[
|
|
This issue was first raised in 1999, but it slipped through
|
|
the cracks.
|
|
]</i></p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the Note in section 17.4.1.2p5 from</p>
|
|
|
|
<blockquote>
|
|
Note: the names defined as macros in C include the following:
|
|
assert, errno, offsetof, setjmp, va_arg, va_end, and va_start.
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
Note: the names defined as macros in C include the following:
|
|
assert, offsetof, setjmp, va_arg, va_end, and va_start.
|
|
</blockquote>
|
|
|
|
<p>In section 19.3, change paragraph 2 from</p>
|
|
|
|
<blockquote>
|
|
The contents are the same as the Standard C library header
|
|
<errno.h>.
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
The contents are the same as the Standard C library header
|
|
<errno.h>, except that errno shall be defined as a macro.
|
|
</blockquote>
|
|
<p><b>Rationale:</b></p>
|
|
<p>C++ must not leave it up to the implementation to decide whether
|
|
or not a name is a macro; it must explicitly specify exactly which
|
|
names are required to be macros.</p>
|
|
<hr>
|
|
<a name="311"><h3>311. Incorrect wording in basic_ostream class synopsis</h3></a><p>
|
|
<b>Section:</b> 27.6.2.1 <a href="lib-iostreams.html#lib.ostream"> [lib.ostream]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Andy Sawyer <b>Date:</b> 21 Mar 2001</p>
|
|
|
|
<p>In 27.6.2.1 <a href="lib-iostreams.html#lib.ostream"> [lib.ostream]</a>, the synopsis of class basic_ostream says:</p>
|
|
|
|
<pre>
|
|
// partial specializationss
|
|
template<class traits>
|
|
basic_ostream<char,traits>& operator<<( basic_ostream<char,traits>&,
|
|
const char * );
|
|
</pre>
|
|
|
|
<p>Problems:</p>
|
|
<ul>
|
|
<li>Too many 's's at the end of "specializationss" </li>
|
|
<li>This is an overload, not a partial specialization</li>
|
|
</ul>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In the synopsis in 27.6.2.1 <a href="lib-iostreams.html#lib.ostream"> [lib.ostream]</a>, remove the
|
|
<i>// partial specializationss</i> comment. Also remove the same
|
|
comment (correctly spelled, but still incorrect) from the synopsis in
|
|
27.6.2.5.4 <a href="lib-iostreams.html#lib.ostream.inserters.character"> [lib.ostream.inserters.character]</a>.
|
|
</p>
|
|
|
|
<p><i>[
|
|
Pre-Redmond: added 27.6.2.5.4 <a href="lib-iostreams.html#lib.ostream.inserters.character"> [lib.ostream.inserters.character]</a> because of Martin's
|
|
comment in c++std-lib-8939.
|
|
]</i></p>
|
|
|
|
<hr>
|
|
<a name="315"><h3>315. Bad "range" in list::unique complexity</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#Ready">Ready</a> <b>Submitter:</b> Andy Sawyer <b>Date:</b> 1 May 2001</p>
|
|
<p>
|
|
23.2.2.4 <a href="lib-containers.html#lib.list.ops"> [lib.list.ops]</a>, Para 21 describes the complexity of
|
|
list::unique as: "If the range (last - first) is not empty, exactly
|
|
(last - first) -1 applications of the corresponding predicate,
|
|
otherwise no applications of the predicate)".
|
|
</p>
|
|
|
|
<p>
|
|
"(last - first)" is not a range.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Change the "range" from (last - first) to [first, last).
|
|
</p>
|
|
<hr>
|
|
<a name="316"><h3>316. Vague text in Table 69</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> Martin Sebor <b>Date:</b> 4 May 2001</p>
|
|
<p>Table 69 says this about a_uniq.insert(t):</p>
|
|
|
|
<blockquote>
|
|
inserts t if and only if there is no element in the container with key
|
|
equivalent to the key of t. The bool component of the returned pair
|
|
indicates whether the insertion takes place and the iterator component of the
|
|
pair points to the element with key equivalent to the key of t.
|
|
</blockquote>
|
|
|
|
<p>The description should be more specific about exactly how the bool component
|
|
indicates whether the insertion takes place.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the text in question to</p>
|
|
|
|
<blockquote>
|
|
...The bool component of the returned pair is true if and only if the insertion
|
|
takes place...
|
|
</blockquote>
|
|
<hr>
|
|
<a name="317"><h3>317. Instantiation vs. specialization of facets</h3></a><p>
|
|
<b>Section:</b> 22 <a href="lib-locales.html#lib.localization"> [lib.localization]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 4 May 2001</p>
|
|
<p>
|
|
The localization section of the standard refers to specializations of
|
|
the facet templates as instantiations even though the required facets
|
|
are typically specialized rather than explicitly (or implicitly)
|
|
instantiated. In the case of ctype<char> and
|
|
ctype_byname<char> (and the wchar_t versions), these facets are
|
|
actually required to be specialized. The terminology should be
|
|
corrected to make it clear that the standard doesn't mandate explicit
|
|
instantiation (the term specialization encompasses both explicit
|
|
instantiations and specializations).
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In the following paragraphs, replace all occurrences of the word
|
|
instantiation or instantiations with specialization or specializations,
|
|
respectively:
|
|
</p>
|
|
|
|
<blockquote>
|
|
22.1.1.1.1, p4, Table 52, 22.2.1.1, p2, 22.2.1.5, p3, 22.2.1.5.1, p5,
|
|
22.2.1.5.2, p10, 22.2.2, p2, 22.2.3.1, p1, 22.2.3.1.2, p1, p2 and p3,
|
|
22.2.4.1, p1, 22.2.4.1.2, p1, 22,2,5, p1, 22,2,6, p2, 22.2.6.3.2, p7, and
|
|
Footnote 242.
|
|
</blockquote>
|
|
|
|
<p>And change the text in 22.1.1.1.1, p4 from</p>
|
|
|
|
<blockquote>
|
|
An implementation is required to provide those instantiations
|
|
for facet templates identified as members of a category, and
|
|
for those shown in Table 52:
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
An implementation is required to provide those specializations...
|
|
</blockquote>
|
|
|
|
<p><i>[Nathan will review these changes, and will look for places where
|
|
explicit specialization is necessary.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>This is a simple matter of outdated language. The language to
|
|
describe templates was clarified during the standardization process,
|
|
but the wording in clause 22 was never updated to reflect that
|
|
change.</p>
|
|
<hr>
|
|
<a name="318"><h3>318. Misleading comment in definition of numpunct_byname</h3></a><p>
|
|
<b>Section:</b> 22.2.3.2 <a href="lib-locales.html#lib.locale.numpunct.byname"> [lib.locale.numpunct.byname]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 12 May 2001</p>
|
|
<p>The definition of the numpunct_byname template contains the following
|
|
comment:</p>
|
|
|
|
<pre>
|
|
namespace std {
|
|
template <class charT>
|
|
class numpunct_byname : public numpunct<charT> {
|
|
// this class is specialized for char and wchar_t.
|
|
...
|
|
</pre>
|
|
|
|
<p>There is no documentation of the specializations and it seems
|
|
conceivable that an implementation will not explicitly specialize the
|
|
template at all, but simply provide the primary template.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Remove the comment from the text in 22.2.3.2 and from the proposed
|
|
resolution of library issue <a href="lwg-defects.html#228">228</a>.</p>
|
|
<hr>
|
|
<a name="319"><h3>319. Storage allocation wording confuses "Required behavior", "Requires"</h3></a><p>
|
|
<b>Section:</b> 18.4.1.1 <a href="lib-support.html#lib.new.delete.single"> [lib.new.delete.single]</a>, 18.4.1.2 <a href="lib-support.html#lib.new.delete.array"> [lib.new.delete.array]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Beman Dawes <b>Date:</b> 15 May 2001</p>
|
|
<p>The standard specifies 17.3.1.3 <a href="lib-intro.html#lib.structure.specifications"> [lib.structure.specifications]</a> that "Required
|
|
behavior" elements describe "the semantics of a function definition
|
|
provided by either the implementation or a C++ program."</p>
|
|
|
|
<p>The standard specifies 17.3.1.3 <a href="lib-intro.html#lib.structure.specifications"> [lib.structure.specifications]</a> that "Requires"
|
|
elements describe "the preconditions for calling the function."</p>
|
|
|
|
<p>In the sections noted below, the current wording specifies
|
|
"Required Behavior" for what are actually preconditions, and thus
|
|
should be specified as "Requires".</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>In 18.4.1.1 <a href="lib-support.html#lib.new.delete.single"> [lib.new.delete.single]</a> Para 12 Change:</p>
|
|
<blockquote>
|
|
<p>Required behavior: accept a value of ptr that is null or that was
|
|
returned by an earlier call ...</p>
|
|
</blockquote>
|
|
<p>to:</p>
|
|
<blockquote>
|
|
<p>Requires: the value of ptr is null or the value returned by an
|
|
earlier call ...</p>
|
|
</blockquote>
|
|
|
|
<p>In 18.4.1.2 <a href="lib-support.html#lib.new.delete.array"> [lib.new.delete.array]</a> Para 11 Change:</p>
|
|
<blockquote>
|
|
<p>Required behavior: accept a value of ptr that is null or that was
|
|
returned by an earlier call ...</p>
|
|
</blockquote>
|
|
<p>to:</p>
|
|
<blockquote>
|
|
<p>Requires: the value of ptr is null or the value returned by an
|
|
earlier call ...</p>
|
|
</blockquote>
|
|
|
|
<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#Review">Review</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 a new row:</p>
|
|
<pre>
|
|
a.assign(i,j) void pre: i,j are not iterators into a.
|
|
Replaces elements in a with copies
|
|
of elements in [i, j).
|
|
</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.
|
|
]</i></p>
|
|
|
|
<hr>
|
|
<a name="321"><h3>321. Typo in num_get</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#Ready">Ready</a> <b>Submitter:</b> Kevin Djang <b>Date:</b> 17 May 2001</p>
|
|
<p>
|
|
Section 22.2.2.1.2 at p7 states that "A length specifier is added to
|
|
the conversion function, if needed, as indicated in Table 56."
|
|
However, Table 56 uses the term "length modifier", not "length
|
|
specifier".
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In 22.2.2.1.2 at p7, change the text "A length specifier is added ..."
|
|
to be "A length modifier is added ..."
|
|
</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>C uses the term "length modifier". We should be consistent.</p>
|
|
<hr>
|
|
<a name="322"><h3>322. iterator and const_iterator should have the same value type</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> Matt Austern <b>Date:</b> 17 May 2001</p>
|
|
<p>
|
|
It's widely assumed that, if X is a container,
|
|
iterator_traits<X::iterator>::value_type and
|
|
iterator_traits<X::const_iterator>::value_type should both be
|
|
X::value_type. However, this is nowhere stated. The language in
|
|
Table 65 is not precise about the iterators' value types (it predates
|
|
iterator_traits), and could even be interpreted as saying that
|
|
iterator_traits<X::const_iterator>::value_type should be "const
|
|
X::value_type".
|
|
</p>
|
|
|
|
<p>Related issue: <a href="lwg-closed.html#279">279</a>.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In Table 65 ("Container Requirements"), change the return type for
|
|
X::iterator to "iterator type whose value type is T". Change the
|
|
return type for X::const_iterator to "constant iterator type whose
|
|
value type is T".</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
This belongs as a container requirement, rather than an iterator
|
|
requirement, because the whole notion of iterator/const_iterator
|
|
pairs is specific to containers' iterator.
|
|
</p>
|
|
<p>
|
|
It is existing practice that (for example)
|
|
iterator_traits<list<int>::const_iterator>::value_type
|
|
is "int", rather than "const int". This is consistent with
|
|
the way that const pointers are handled: the standard already
|
|
requires that iterator_traits<const int*>::value_type is int.
|
|
</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#Review">Review</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 itereator.</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#Review">Review</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="327"><h3>327. Typo in time_get facet in table 52</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> Tiki Wan <b>Date:</b> 06 Jul 2001</p>
|
|
<p>The <tt>wchar_t</tt> versions of <tt>time_get</tt> and
|
|
<tt>time_get_byname</tt> are listed incorrectly in table 52,
|
|
required instantiations. In both cases the second template
|
|
parameter is given as OutputIterator. It should instead be
|
|
InputIterator, since these are input facets.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In table 52, required instantiations, in
|
|
22.1.1.1.1 <a href="lib-locales.html#lib.locale.category"> [lib.locale.category]</a>, change</p>
|
|
<pre>
|
|
time_get<wchar_t, OutputIterator>
|
|
time_get_byname<wchar_t, OutputIterator>
|
|
</pre>
|
|
<p>to</p>
|
|
<pre>
|
|
time_get<wchar_t, InputIterator>
|
|
time_get_byname<wchar_t, InputIterator>
|
|
</pre>
|
|
|
|
<p><i>[Redmond: Very minor change in proposed resolution. Original had
|
|
a typo, wchart instead of wchar_t.]</i></p>
|
|
|
|
<hr>
|
|
<a name="328"><h3>328. Bad sprintf format modifier in money_put<>::do_put()</h3></a><p>
|
|
<b>Section:</b> 22.2.6.2.2 <a href="lib-locales.html#lib.locale.money.put.virtuals"> [lib.locale.money.put.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 07 Jul 2001</p>
|
|
<p>The sprintf format string , "%.01f" (that's the digit one), in the
|
|
description of the do_put() member functions of the money_put facet in
|
|
22.2.6.2.2, p1 is incorrect. First, the f format specifier is wrong
|
|
for values of type long double, and second, the precision of 01
|
|
doesn't seem to make sense. What was most likely intended was
|
|
"%.0Lf"., that is a precision of zero followed by the L length
|
|
modifier.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the format string to "%.0Lf".</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>Fixes an obvious typo</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#Review">Review</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="331"><h3>331. bad declaration of destructor for ios_base::failure</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#Ready">Ready</a> <b>Submitter:</b> PremAnand M. Rao <b>Date:</b> 23 Aug 2001</p>
|
|
<p>
|
|
With the change in 17.4.4.8 <a href="lib-intro.html#lib.res.on.exception.handling"> [lib.res.on.exception.handling]</a> to state
|
|
"An implementation may strengthen the exception-specification for a
|
|
non-virtual function by removing listed exceptions."
|
|
(issue <a href="lwg-defects.html#119">119</a>)
|
|
and the following declaration of ~failure() in ios_base::failure
|
|
</p>
|
|
<pre>
|
|
namespace std {
|
|
class ios_base::failure : public exception {
|
|
public:
|
|
...
|
|
virtual ~failure();
|
|
...
|
|
};
|
|
}
|
|
</pre>
|
|
<p>the class failure cannot be implemented since in 18.6.1 <a href="lib-support.html#lib.exception"> [lib.exception]</a> the destructor of class exception has an empty
|
|
exception specification:</p>
|
|
<pre>
|
|
namespace std {
|
|
class exception {
|
|
public:
|
|
...
|
|
virtual ~exception() throw();
|
|
...
|
|
};
|
|
}
|
|
</pre>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Remove the declaration of ~failure().</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>The proposed resolution is consistent with the way that destructors
|
|
of other classes derived from <tt>exception</tt> are handled.</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#Review">Review</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#Review">Review</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>
|
|
|
|
<hr>
|
|
<a name="335"><h3>335. minor issue with char_traits, table 37</h3></a><p>
|
|
<b>Section:</b> 21.1.1 <a href="lib-strings.html#lib.char.traits.require"> [lib.char.traits.require]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Andy Sawyer <b>Date:</b> 06 Sep 2001</p>
|
|
<p>
|
|
Table 37, in 21.1.1 <a href="lib-strings.html#lib.char.traits.require"> [lib.char.traits.require]</a>, descibes char_traits::assign
|
|
as:
|
|
</p>
|
|
<pre>
|
|
X::assign(c,d) assigns c = d.
|
|
</pre>
|
|
|
|
<p>And para 1 says:</p>
|
|
|
|
<blockquote>
|
|
[...] c and d denote values of type CharT [...]
|
|
</blockquote>
|
|
|
|
<p>
|
|
Naturally, if c and d are <i>values</i>, then the assignment is
|
|
(effectively) meaningless. It's clearly intended that (in the case of
|
|
assign, at least), 'c' is intended to be a reference type.
|
|
</p>
|
|
|
|
<p>I did a quick survey of the four implementations I happened to have
|
|
lying around, and sure enough they all have signatures:</p>
|
|
<pre>
|
|
assign( charT&, const charT& );
|
|
</pre>
|
|
|
|
<p>(or the equivalent). It's also described this way in Nico's book.
|
|
(Not to mention the synopses of char_traits<char> in 21.1.3.1
|
|
and char_traits<wchar_t> in 21.1.3.2...)
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Add the following to 21.1.1 para 1:</p>
|
|
<blockquote>
|
|
r denotes an lvalue of CharT
|
|
</blockquote>
|
|
|
|
<p>and change the description of assign in the table to:</p>
|
|
<pre>
|
|
X::assign(r,d) assigns r = d
|
|
</pre>
|
|
<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>
|
|
<hr>
|
|
<a name="337"><h3>337. replace_copy_if's template parameter should be InputIterator</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#Ready">Ready</a> <b>Submitter:</b> Detlef Vollmann <b>Date:</b> 07 Sep 2001</p>
|
|
<p>From c++std-edit-876:</p>
|
|
|
|
<p>
|
|
In section 25.2.4 <a href="lib-algorithms.html#lib.alg.replace"> [lib.alg.replace]</a> before p4: The name of the first
|
|
parameter of template replace_copy_if should be "InputIterator"
|
|
instead of "Iterator". According to 17.3.2.1 <a href="lib-intro.html#lib.type.descriptions"> [lib.type.descriptions]</a> p1 the
|
|
parameter name conveys real normative meaning.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change <tt>Iterator</tt> to <tt>InputIterator</tt>.</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#Review">Review</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#Review">Review</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 T 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>
|
|
|
|
<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#Review">Review</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#Review">Review</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.
|
|
ay be useful.
|
|
</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="345"><h3>345. type tm in <cwchar></h3></a><p>
|
|
<b>Section:</b> 21.4 <a href="lib-strings.html#lib.c.strings"> [lib.c.strings]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Clark Nelson <b>Date:</b> 19 Oct 2001</p>
|
|
<p>
|
|
C99, and presumably amendment 1 to C90, specify that <wchar.h>
|
|
declares struct tm as an incomplete type. However, table 48 in 21.4 <a href="lib-strings.html#lib.c.strings"> [lib.c.strings]</a> does not mention the type tm as being declared in
|
|
<cwchar>. Is this omission intentional or accidental?
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In section 21.4 <a href="lib-strings.html#lib.c.strings"> [lib.c.strings]</a>, add "tm" to table 48.</p>
|
|
<hr>
|
|
<a name="346"><h3>346. Some iterator member functions should be const</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#Ready">Ready</a> <b>Submitter:</b> Jeremy Siek <b>Date:</b> 20 Oct 2001</p>
|
|
<p>Iterator member functions and operators that do not change the state
|
|
of the iterator should be defined as const member functions or as
|
|
functions that take iterators either by const reference or by
|
|
value. The standard does not explicitly state which functions should
|
|
be const. Since this a fairly common mistake, the following changes
|
|
are suggested to make this explicit.</p>
|
|
|
|
<p>The tables almost indicate constness properly through naming: r
|
|
for non-const and a,b for const iterators. The following changes
|
|
make this more explicit and also fix a couple problems.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 24.1 <a href="lib-iterators.html#lib.iterator.requirements"> [lib.iterator.requirements]</a> Change the first section of p9 from
|
|
"In the following sections, a and b denote values of X..." to
|
|
"In the following sections, a and b denote values of type const X...".</p>
|
|
|
|
<p>In Table 73, change</p>
|
|
<pre>
|
|
a->m U& ...
|
|
</pre>
|
|
|
|
<p>to</p>
|
|
|
|
<pre>
|
|
a->m const U& ...
|
|
r->m U& ...
|
|
</pre>
|
|
|
|
<p>In Table 73 expression column, change</p>
|
|
|
|
<pre>
|
|
*a = t
|
|
</pre>
|
|
|
|
<p>to</p>
|
|
|
|
<pre>
|
|
*r = t
|
|
</pre>
|
|
|
|
<p><i>[Redmond: The container requirements should be reviewed to see if
|
|
the same problem appears there.]</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#New">New</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>
|
|
|
|
<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#New">New</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>
|
|
<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#New">New</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#New">New</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><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><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>
|
|
<p>----- End of document -----</p>
|
|
</body>
|
|
</html>
|