mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-23 13:09:49 +08:00
77cd227ec3
2001-09-25 Phil Edwards <pme@gcc.gnu.org> * docs/html/20_util/howto.html: Add anchor name. * docs/html/23_containers/howto.html: Line wrapping, another link. * docs/html/25_algorithms/howto.html: Another note. * docs/html/ext/howto.html: Link to SGI extensions. List DRs and link to them... * docs/html/ext/lwg-active.html: ...in this new file (from R19), * docs/html/ext/lwg-defects.html: and this new file (from R19). * docs/html/ext/sgiexts.html: New file. Mention SGI extensions carried over to libstdc++-v3. * docs/html/faq/index.html: Link to SGI extensions. Mention the "missing .." pseudobug. * docs/html/faq/index.txt: Regenerate. * include/bits/ios_base.h: DR-related comment cleanup. * include/bits/istream.tcc: Likewise. * include/bits/locale_facets.h: Likewise. * include/bits/locale_facets.tcc: Likewise. * include/bits/ostream.tcc: Likewise. * include/bits/std_bitset.h: Likewise. * include/bits/std_iosfwd.h: Likewise. * include/bits/std_istream.h: Likewise. * include/bits/std_ostream.h: Likewise. * include/bits/std_streambuf.h: Likewise. * include/bits/stl_pair.h: Likewise. * include/bits/streambuf_iterator.h: Likewise. * include/bits/std_map.h: Remove unused header inclusion guard _CPP_BITS_STL_TREE_H from around bits/stl_tree.h. * include/bits/std_set.h: Likewise. * include/bits/stl_function.h: Doxygen markup. * docs/doxygen/doxygroups.cc: New file, specifying module grouping. * libsupc++/typeinfo: Doxygen markup tweak. From-SVN: r45816
6443 lines
274 KiB
HTML
6443 lines
274 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-0031 = WG21 N1317</td>
|
|
</tr>
|
|
<tr>
|
|
<td align="left">Date:</td>
|
|
<td align="left">11 Sep 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 19)</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>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-active.html#312">312</a>-<a href="lwg-active.html#317">317</a>, and discussed
|
|
new issues <a href="lwg-active.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-active.html#49">49</a> <a href="lwg-active.html#109">109</a> <a href="lwg-active.html#117">117</a> <a href="lwg-active.html#182">182</a>
|
|
<a href="lwg-active.html#228">228</a> <a href="lwg-active.html#230">230</a> <a href="lwg-active.html#232">232</a> <a href="lwg-active.html#235">235</a>
|
|
<a href="lwg-active.html#238">238</a> <a href="lwg-active.html#241">241</a> <a href="lwg-active.html#242">242</a> <a href="lwg-active.html#250">250</a>
|
|
<a href="lwg-active.html#259">259</a> <a href="lwg-active.html#264">264</a> <a href="lwg-active.html#266">266</a> <a href="lwg-active.html#267">267</a>
|
|
<a href="lwg-active.html#271">271</a> <a href="lwg-active.html#272">272</a> <a href="lwg-active.html#273">273</a> <a href="lwg-active.html#275">275</a>
|
|
<a href="lwg-active.html#281">281</a> <a href="lwg-active.html#284">284</a> <a href="lwg-active.html#285">285</a> <a href="lwg-active.html#286">286</a>
|
|
<a href="lwg-active.html#288">288</a> <a href="lwg-active.html#292">292</a> <a href="lwg-active.html#295">295</a> <a href="lwg-active.html#297">297</a>
|
|
<a href="lwg-active.html#298">298</a> <a href="lwg-active.html#301">301</a> <a href="lwg-active.html#303">303</a> <a href="lwg-active.html#306">306</a>
|
|
<a href="lwg-active.html#307">307</a> <a href="lwg-active.html#308">308</a> <a href="lwg-active.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-active.html#49">49</a>, <a href="lwg-active.html#76">76</a>, <a href="lwg-active.html#91">91</a>, <a href="lwg-active.html#235">235</a>, <a href="lwg-active.html#250">250</a>, <a href="lwg-active.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-active.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-active.html#228">228</a> to <a href="lwg-active.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-active.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-active.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
|
|
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>
|
|
Now the proposed resolution results in not modifying the value passed
|
|
as last argument if an overflow is encountered but <tt>failbit</tt>
|
|
is set. Checking <tt>errno</tt> for <tt>ERANGE</tt> still allows for
|
|
detection of an overflow but not what the sign was.
|
|
</p>
|
|
|
|
<p>
|
|
Actually, my problem is not that much with the sign but this is at least
|
|
making things worse... My problem is more that it is still necessary
|
|
to check <tt>errno</tt> for the error description. Thus, I propose the
|
|
following resolution:
|
|
</p>
|
|
|
|
<p>Change paragraph 11 from</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
<b>-11-</b> <b>Stage 3:</b>
|
|
The result of stage 2 processing can be one of</p>
|
|
|
|
<ul>
|
|
<li>A sequence of <tt>char</tt>s
|
|
has been accumulated in stage 2 that is converted (according to the
|
|
rules of <tt>scanf)</tt> to a value of the type of <tt><i>val</i></tt>.
|
|
This value is stored in <tt><i>val</i></tt> and
|
|
<tt>ios_base::goodbit</tt> is stored in <tt><i>err</i></tt>.</li>
|
|
|
|
<li>The sequence of <tt>char</tt>s
|
|
accumulated in stage 2 would have caused scanf to report an input failure.
|
|
<tt>ios_base::failbit</tt> is assigned to <i>err</i>.</li>
|
|
</ul>
|
|
</blockquote>
|
|
|
|
<p>to become</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
<b>-11-</b> <b>Stage 3:</b>
|
|
The result of stage 2 processing can be one of</p>
|
|
|
|
<ul>
|
|
<li>A sequence of <tt>char</tt>s
|
|
has been accumulated in stage 2 that is converted (according to the
|
|
rules of <tt>scanf)</tt> to a value of the type of <tt><i>val</i></tt>.
|
|
This value is stored in <tt><i>val</i></tt>. If the conversion reported
|
|
an overflow error for the type of <tt><i>val</i></tt> (ie.
|
|
<tt><i>errno</i></tt> would be set to <tt>ERANGE</tt> by the used
|
|
conversion function) then <tt>ios_base::failbit</tt> is stored in
|
|
<tt><i>err</i></tt>, otherwise <tt>ios_base::goodbit</tt> is stored in
|
|
<tt><i>err</i></tt>.</li>
|
|
|
|
<li>The sequence of <tt>char</tt>s accumulated in stage 2 would have
|
|
caused scanf to report an input failure. <tt>ios_base::failbit</tt>
|
|
is assigned to <i>err</i>.</li>
|
|
</ul>
|
|
</blockquote>
|
|
|
|
<p>
|
|
With this definition, overflow can be detected easily by storing a value
|
|
different from the maximum value in <tt><i>val</i></tt> and checking whether
|
|
this value was modified in case <tt>failbit</tt> is set: If it was, there
|
|
was an overflow error, otherwise some other input error occurred (under the
|
|
conditions for the second bullet <tt><i>val</i></tt> is not changed).
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 22.2.2.1.2 , paragraph 11, second bullet item,
|
|
change </p>
|
|
|
|
<blockquote>
|
|
<p>The sequence of chars accumulated in stage 2 would have caused scanf to report an input
|
|
failure. </p>
|
|
</blockquote>
|
|
|
|
<p>to </p>
|
|
|
|
<blockquote>
|
|
<p>The sequence of chars accumulated in stage 2 would have caused scanf to report an input
|
|
failure, or the value of the sequence cannot be represented in the type of _val_. </p>
|
|
</blockquote>
|
|
|
|
<p><i>[post-Toronto: "cannot be represented" is probably wrong:
|
|
infinity can be represented on an IEC559 platform, but 0.1 cannot be
|
|
represented exactly. However, the alternate proposal may be wrong as
|
|
well. It's not clear whether overflow (and underflow?) should always
|
|
be treated as errors. This issue requires much more thought]</i></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="49"><h3>49. Underspecification of ios_base::sync_with_stdio</h3></a><p>
|
|
<b>Section:</b> 27.4.2.4 <a href="lib-iostreams.html#lib.ios.members.static"> [lib.ios.members.static]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 21 Jun 1998</p>
|
|
<p>Two problems</p>
|
|
|
|
<p>(1) 27.4.2.4 doesn't say what ios_base::sync_with_stdio(f)
|
|
returns. Does it return f, or does it return the previous
|
|
synchronization state? My guess is the latter, but the standard
|
|
doesn't say so.</p>
|
|
|
|
<p>(2) 27.4.2.4 doesn't say what it means for streams to be
|
|
synchronized with stdio. Again, of course, I can make some
|
|
guesses. (And I'm unhappy about the performance implications of those
|
|
guesses, but that's another matter.)</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the following sentence in 27.4.2.4
|
|
returns clause from:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
<tt>true</tt> if the standard iostream objects (27.3) are
|
|
synchronized and otherwise returns <tt>false</tt>.</p>
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
<tt>true</tt> if the previous state of the standard iostream
|
|
objects (27.3) was synchronized and otherwise returns
|
|
<tt>false</tt>.</p>
|
|
</blockquote>
|
|
|
|
<p>Add the following immediately after 27.4.2.4 ,
|
|
paragraph 2:</p>
|
|
|
|
<blockquote>
|
|
<p>When a standard iostream object str is <i>synchronized</i> with a
|
|
standard stdio stream f, the effect of inserting a character c by</p>
|
|
<pre>
|
|
fputc(f, c);
|
|
</pre>
|
|
|
|
<p>is the same as the effect of</p>
|
|
<pre>
|
|
str.rdbuf()->sputc(c);
|
|
</pre>
|
|
|
|
<p>for any sequence of characters; the effect of extracting a
|
|
character c by</p>
|
|
<pre>
|
|
c = fgetc(f);
|
|
</pre>
|
|
|
|
<p>is the same as the effect of:</p>
|
|
<pre>
|
|
c = str.rdbuf()->sbumpc(c);
|
|
</pre>
|
|
|
|
<p>for any sequences of characters; and the effect of pushing
|
|
back a character c by</p>
|
|
<pre>
|
|
ungetc(c, f);
|
|
</pre>
|
|
|
|
<p>is the same as the effect of</p>
|
|
<pre>
|
|
str.rdbuf()->sputbackc(c);
|
|
</pre>
|
|
|
|
<p>for any sequence of characters. [<i>Footnote</i>: This implies
|
|
that operations on a standard iostream object can be mixed arbitrarily
|
|
with operations on the corresponding stdio stream. In practical
|
|
terms, synchronization usually means that a standard iostream object
|
|
and a standard stdio object share a buffer. <i>--End Footnote</i>]</p>
|
|
</blockquote>
|
|
|
|
<p><i>[pre-Copenhagen: PJP and Matt contributed the definition
|
|
of "synchronization"]</i></p>
|
|
|
|
<p><i>[post-Copenhagen: proposed resolution was revised slightly:
|
|
text was added in the non-normative footnote to say that operations
|
|
on the two streams can be mixed arbitrarily.]</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#Review">Review</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 ,
|
|
paragraph 11) and <tt>basic_filebuf::underflow</tt> (27.8.1.4 , 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 paragraph 2:</p>
|
|
|
|
<blockquote>
|
|
<p>A <tt>codecvt</tt> facet that is used by <tt>basic_filebuf</tt>
|
|
(27.8 ) must have the property that if</p>
|
|
<pre>
|
|
do_out(state, from, from_end, from_next, to, to_lim, to_next)
|
|
</pre>
|
|
would succeed (return value would be <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 succeed, and that if
|
|
<pre>
|
|
do_in(state, from, from_end, from_next, to, to_lim, to_next)
|
|
</pre>
|
|
would succeed, 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 succeed. [<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><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 , 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 an unformatted input function (27.6.1.2 ). 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 , 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.2 ). 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><b>Rationale:</b></p>
|
|
<p>The real issue here is whether or not these string input functions
|
|
perform formatted input. If they do, then they get their characters
|
|
from a streambuf, rather than by calling an istream's member functions,
|
|
and a streambuf signals failure either by returning eof or by throwing
|
|
an exception. The proposed resolution makes it clear that these two
|
|
functions do perform formatted input.</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 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 specifies semantics for
|
|
<tt>*r++</tt> of:</p>
|
|
|
|
<p> <tt>{ T tmp = *r; ++r; return tmp; }</tt>
|
|
</p>
|
|
|
|
<p>This does not work for pointers and over constrains implementors.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Add for *r++: “To call the copy constructor for the type T is
|
|
allowed but not required.”</p>
|
|
|
|
<p><i>[Dublin: Pete Becker will attempt improved wording.]</i></p>
|
|
|
|
<p><i>[Tokyo: The essence of the issue seems to have escaped.
|
|
Pete will email Valentin to try to recapture it.]</i></p>
|
|
<hr>
|
|
<a name="109"><h3>109. Missing binders for non-const sequence elements</h3></a><p>
|
|
<b>Section:</b> 20.3.6 <a href="lib-utilities.html#lib.binders"> [lib.binders]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Bjarne Stroustrup <b>Date:</b> 7 Oct 1998</p>
|
|
<p>There are no versions of binders that apply to non-const elements
|
|
of a sequence. This makes examples like for_each() using bind2nd() on
|
|
page 521 of "The C++ Programming Language (3rd)"
|
|
non-conforming. Suitable versions of the binders need to be added.</p>
|
|
|
|
<p>Further discussion from Nico:</p>
|
|
|
|
<p>What is probably meant here is shown in the following example:</p>
|
|
|
|
<pre>class Elem {
|
|
public:
|
|
void print (int i) const { }
|
|
void modify (int i) { }
|
|
}; </pre>
|
|
<pre>int main()
|
|
{
|
|
vector<Elem> coll(2);
|
|
for_each (coll.begin(), coll.end(), bind2nd(mem_fun_ref(&Elem::print),42)); // OK
|
|
for_each (coll.begin(), coll.end(), bind2nd(mem_fun_ref(&Elem::modify),42)); // ERROR
|
|
}</pre>
|
|
|
|
<p>The error results from the fact that bind2nd() passes its first
|
|
argument (the argument of the sequence) as constant reference. See the
|
|
following typical implementation:</p>
|
|
|
|
<blockquote>
|
|
<pre>template <class Operation>
|
|
class binder2nd
|
|
: public unary_function<typename Operation::first_argument_type,
|
|
typename Operation::result_type> {
|
|
protected:
|
|
Operation op;
|
|
typename Operation::second_argument_type value;
|
|
public:
|
|
binder2nd(const Operation& o,
|
|
const typename Operation::second_argument_type& v)
|
|
: op(o), value(v) {} </pre>
|
|
<pre> typename Operation::result_type
|
|
operator()(const typename Operation::first_argument_type& x) const {
|
|
return op(x, value);
|
|
}
|
|
};</pre>
|
|
</blockquote>
|
|
|
|
<p>The solution is to overload operator () of bind2nd for non-constant arguments:</p>
|
|
|
|
<blockquote>
|
|
<pre>template <class Operation>
|
|
class binder2nd
|
|
: public unary_function<typename Operation::first_argument_type,
|
|
typename Operation::result_type> {
|
|
protected:
|
|
Operation op;
|
|
typename Operation::second_argument_type value;
|
|
public:
|
|
binder2nd(const Operation& o,
|
|
const typename Operation::second_argument_type& v)
|
|
: op(o), value(v) {} </pre>
|
|
<pre> typename Operation::result_type
|
|
operator()(const typename Operation::first_argument_type& x) const {
|
|
return op(x, value);
|
|
}
|
|
typename Operation::result_type
|
|
operator()(typename Operation::first_argument_type& x) const {
|
|
return op(x, value);
|
|
}
|
|
};</pre>
|
|
</blockquote>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 20.3.6.1 in the declaration of binder1st after:</p>
|
|
<blockquote>
|
|
<p><tt>typename Operation::result_type<br>
|
|
operator()(const typename Operation::second_argument_type& x) const;</tt></p>
|
|
</blockquote>
|
|
<p>insert:</p>
|
|
<blockquote>
|
|
<p><tt>typename Operation::result_type<br>
|
|
operator()(typename Operation::second_argument_type& x) const;</tt></p>
|
|
</blockquote>
|
|
<p>In 20.3.6.3 in the declaration of binder2nd after:</p>
|
|
<blockquote>
|
|
<p><tt>typename Operation::result_type<br>
|
|
operator()(const typename Operation::first_argument_type& x) const;</tt></p>
|
|
</blockquote>
|
|
<p>insert:</p>
|
|
<blockquote>
|
|
<p><tt>typename Operation::result_type<br>
|
|
operator()(typename Operation::first_argument_type& x) const;</tt></p>
|
|
</blockquote>
|
|
|
|
<p><i>[Kona: The LWG discussed this at some length.It was agreed that
|
|
this is a mistake in the design, but there was no consensus on whether
|
|
it was a defect in the Standard. Straw vote: NAD - 5. Accept
|
|
proposed resolution - 3. Leave open - 6.]</i></p>
|
|
|
|
<p><i>[Copenhagen: It was generally agreed that this was a defect.
|
|
Strap poll: NAD - 0. Accept proposed resolution - 10.
|
|
Leave open - 1.]</i></p>
|
|
|
|
<hr>
|
|
<a name="117"><h3>117. <tt>basic_ostream</tt> uses nonexistent <tt>num_put</tt> member functions</h3></a><p>
|
|
<b>Section:</b> 27.6.2.5.2 <a href="lib-iostreams.html#lib.ostream.inserters.arithmetic"> [lib.ostream.inserters.arithmetic]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 20 Nov 1998</p>
|
|
<p>The <b>effects</b> clause for numeric inserters says that
|
|
insertion of a value <tt>x</tt>, whose type is either <tt>bool</tt>,
|
|
<tt>short</tt>, <tt>unsigned short</tt>, <tt>int</tt>, <tt>unsigned
|
|
int</tt>, <tt>long</tt>, <tt>unsigned long</tt>, <tt>float</tt>,
|
|
<tt>double</tt>, <tt>long double</tt>, or <tt>const void*</tt>, is
|
|
delegated to <tt>num_put</tt>, and that insertion is performed as if
|
|
through the following code fragment: </p>
|
|
|
|
<pre>bool failed = use_facet<
|
|
num_put<charT,ostreambuf_iterator<charT,traits> >
|
|
>(getloc()).put(*this, *this, fill(), val). failed();</pre>
|
|
|
|
<p>This doesn't work, because <tt>num_put<></tt>::put is only
|
|
overloaded for the types <tt>bool</tt>, <tt>long</tt>, <tt>unsigned
|
|
long</tt>, <tt>double</tt>, <tt>long double</tt>, and <tt>const
|
|
void*</tt>. That is, the code fragment in the standard is incorrect
|
|
(it is diagnosed as ambiguous at compile time) for the types
|
|
<tt>short</tt>, <tt>unsigned short</tt>, <tt>int</tt>, <tt>unsigned
|
|
int</tt>, and <tt>float</tt>. </p>
|
|
|
|
<p>We must either add new member functions to <tt>num_put</tt>, or
|
|
else change the description in <tt>ostream</tt> so that it only calls
|
|
functions that are actually there. I prefer the latter. </p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Replace 27.6.2.5.2, paragraph 1 with the following: </p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
The classes num_get<> and num_put<> handle locale­dependent numeric
|
|
formatting and parsing. These inserter functions use the imbued
|
|
locale value to perform numeric formatting. When val is of type bool,
|
|
long, unsigned long, double, long double, or const void*, the
|
|
formatting conversion occurs as if it performed the following code
|
|
fragment:
|
|
</p>
|
|
|
|
<pre>
|
|
bool failed = use_facet<
|
|
num_put<charT,ostreambuf_iterator<charT,traits> >
|
|
>(getloc()).put(*this, *this, fill(), val). failed();
|
|
</pre>
|
|
|
|
<p>
|
|
When val is of type short the formatting conversion occurs as if it
|
|
performed the following code fragment:
|
|
</p>
|
|
|
|
<pre>
|
|
ios_base::fmtflags baseflags = ios_base::flags() & ios_base::basefield;
|
|
bool failed = use_facet<
|
|
num_put<charT,ostreambuf_iterator<charT,traits> >
|
|
>(getloc()).put(*this, *this, fill(),
|
|
baseflags == ios_base::oct || baseflags == ios_base::hex
|
|
? static_cast<long>(static_cast<unsigned short>(val))
|
|
: static_cast<long>(val)). failed();
|
|
</pre>
|
|
|
|
<p>
|
|
When val is of type int the formatting conversion occurs as if it performed
|
|
the following code fragment:
|
|
</p>
|
|
|
|
<pre>
|
|
ios_base::fmtflags baseflags = ios_base::flags() & ios_base::basefield;
|
|
bool failed = use_facet<
|
|
num_put<charT,ostreambuf_iterator<charT,traits> >
|
|
>(getloc()).put(*this, *this, fill(),
|
|
baseflags == ios_base::oct || baseflags == ios_base::hex
|
|
? static_cast<long>(static_cast<unsigned int>(val))
|
|
: static_cast<long>(val)). failed();
|
|
</pre>
|
|
|
|
<p>
|
|
When val is of type unsigned short or unsigned int the formatting conversion
|
|
occurs as if it performed the following code fragment:
|
|
</p>
|
|
|
|
<pre>
|
|
bool failed = use_facet<
|
|
num_put<charT,ostreambuf_iterator<charT,traits> >
|
|
>(getloc()).put(*this, *this, fill(), static_cast<unsigned long>(val)).
|
|
failed();
|
|
</pre>
|
|
|
|
<p>
|
|
When val is of type float the formatting conversion occurs as if it
|
|
performed the following code fragment:
|
|
</p>
|
|
|
|
<pre>
|
|
bool failed = use_facet<
|
|
num_put<charT,ostreambuf_iterator<charT,traits> >
|
|
>(getloc()).put(*this, *this, fill(), static_cast<double>(val)).
|
|
failed();
|
|
</pre>
|
|
|
|
</blockquote>
|
|
|
|
<p><i>[post-Toronto: This differs from the previous proposed
|
|
resolution; PJP provided the new wording. The differences are in
|
|
signed short and int output.]</i></p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>The original proposed resolution was to cast int and short to long,
|
|
unsigned int and unsigned short to unsigned long, and float to double,
|
|
thus ensuring that we don't try to use nonexistent num_put<>
|
|
member functions. The current proposed resolution is more
|
|
complicated, but gives more expected results for hex and octal output
|
|
of signed short and signed int. (On a system with 16-bit short, for
|
|
example, printing short(-1) in hex format should yield 0xffff.)</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>Section 17.4.3.1 says: </p>
|
|
|
|
<blockquote>
|
|
<p>It is undefined for a C++ program to add declarations or definitions to namespace std
|
|
or namespaces within namespace std unless otherwise specified. A program may add template
|
|
specializations for any standard library template to namespace std. Such a specialization
|
|
(complete or partial) of a standard library template results in undefined behavior unless
|
|
the declaration depends on a user-defined name of external linkage and unless the
|
|
specialization meets the standard library requirements for the original template... </p>
|
|
</blockquote>
|
|
|
|
<p>This implies that it is ok for library users to add specializations, but not
|
|
implementors. A user program can actually detect this, for example, the following manual
|
|
instantiation will not compile if the implementor has made ctype<wchar_t> a
|
|
specialization: </p>
|
|
|
|
<pre>
|
|
#include <locale>
|
|
#include <wchar.h>
|
|
|
|
template class std::ctype<wchar_t>; // can't be specialization
|
|
</pre>
|
|
|
|
<p>
|
|
Lib-7047 Matt Austern comments:
|
|
</p>
|
|
<blockquote>
|
|
<p>The status quo is unclear, and probably contradictory. This issue
|
|
applies both to explicit instantiations and to specializations, since
|
|
it is not permitted to provide both a specialization and an explicit
|
|
instantiation.
|
|
</p>
|
|
<p>
|
|
The specialization issue is actually more serious than the
|
|
instantiation one.
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p>In Copenhagen, core working group decided on a proposed 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><b>Proposed resolution:</b></p>
|
|
<p>Option 1.</p>
|
|
<blockquote>
|
|
<p>Append to 17.4.3.1 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 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 must document the templates
|
|
they have explicitly instantiated. (C) Users may explicitly
|
|
instantiate any standard library template. Consequence: library
|
|
implementors may freely specialize templates, but may not explicitly
|
|
instantiate them. This is a serious burden for implementors; one way
|
|
they can manage it is by defining the standard template as a wrapper,
|
|
and putting all of the real work in an internal helper class/function.
|
|
]</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>
|
|
<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#Open">Open</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 is const: </p>
|
|
|
|
<p> <tt>void operator=(const valarray<T>&) const;</tt> </p>
|
|
|
|
<p>but this one in Section 26.3.5.4 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>Make the <tt>operator=(const T&)</tt> versions of slice_array, gslice_array,
|
|
indirect_array, and mask_array <tt>const</tt> member functions. </p>
|
|
|
|
<p><i>[Dublin: Pete Becker spoke to Daveed Vandevoorde about this and will work on a
|
|
proposed resolution.]</i></p>
|
|
|
|
<p><i>[Tokyo: Discussed together with the AFNOR paper
|
|
00-0023/N1246. The current helper slices now violate language rules
|
|
due to a core language change (but most compilers don't check, so the
|
|
violation has previously gone undetected). Major surgery is being
|
|
asked for in this and other valarray proposals (see issue <a href="lwg-closed.html#77">77</a>Rationale), and a complete design review is needed before
|
|
making piecemeal changes. Robert Klarer will work on formulating the
|
|
issues.]</i></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#Review">Review</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 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>In section 23.1 after paragraph 7 add:</p>
|
|
<blockquote>
|
|
<p>It is possible to mix <tt>iterator</tt>s and
|
|
<tt>const_iterator</tt>s in iterator comparison and
|
|
iterator difference operations.</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Post-Tokyo: Judy supplied the above wording at the request of
|
|
the LWG.]</i></p>
|
|
|
|
<p><i>[post-Toronto: Judy supplied a new proposed resolution. The old
|
|
version did not include the words "and iterator
|
|
difference".]</i></p>
|
|
|
|
<p><i>[Copenhagen: There was some concern that "it is possible
|
|
to mix" might be too informal. Howard and Dave will provide new
|
|
wording, which will involve a list of expressions that are
|
|
guaranteed to be valid.]</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="182"><h3>182. Ambiguous references to size_t</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#Ready">Ready</a> <b>Submitter:</b> Al Stevens <b>Date:</b> 15 Aug 1999</p>
|
|
<p>Many references to <tt> size_t</tt> throughout the document
|
|
omit the <tt> std::</tt> namespace qualification.</p> <p>For
|
|
example, 17.4.3.4 paragraph 2:</p>
|
|
<blockquote>
|
|
<pre>— operator new(size_t)
|
|
— operator new(size_t, const std::nothrow_t&)
|
|
— operator new[](size_t)
|
|
— operator new[](size_t, const std::nothrow_t&)</pre>
|
|
</blockquote>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p> In 17.4.3.4 paragraph 2: replace:</p>
|
|
<blockquote>
|
|
<p><tt> - operator new(size_t)<br>
|
|
- operator new(size_t, const std::nothrow_t&)<br>
|
|
- operator new[](size_t)<br>
|
|
- operator new[](size_t, const std::nothrow_t&)</tt></p>
|
|
</blockquote>
|
|
<p> by:</p>
|
|
<blockquote>
|
|
<pre>- operator new(std::size_t)
|
|
- operator new(std::size_t, const std::nothrow_t&)
|
|
- operator new[](std::size_t)
|
|
- operator new[](std::size_t, const std::nothrow_t&)</pre>
|
|
</blockquote>
|
|
<p>In [lib.allocator.requirements] 20.1.5, paragraph 4: replace:</p>
|
|
<blockquote>
|
|
<p>The typedef members pointer, const_pointer, size_type, and difference_type
|
|
are required to be T*, T const*, size_t, and ptrdiff_t, respectively.</p>
|
|
</blockquote>
|
|
<p> by:</p>
|
|
<blockquote>
|
|
<p>The typedef members pointer, const_pointer, size_type, and difference_type
|
|
are required to be T*, T const*, std::size_t, and std::ptrdiff_t,
|
|
respectively.</p>
|
|
</blockquote>
|
|
<p>In [lib.allocator.members] 20.4.1.1, paragraphs 3 and 6: replace:</p>
|
|
<blockquote>
|
|
<p>3 Notes: Uses ::operator new(size_t) (18.4.1).</p>
|
|
<p>6 Note: the storage is obtained by calling ::operator new(size_t), but it
|
|
is unspecified when or how often this function is called. The use of hint is
|
|
unspecified, but intended as an aid to locality if an implementation so
|
|
desires.</p>
|
|
</blockquote>
|
|
<p>by:</p>
|
|
<blockquote>
|
|
<p>3 Notes: Uses ::operator new(std::size_t) (18.4.1).</p>
|
|
<p>6 Note: the storage is obtained by calling ::operator new(std::size_t), but
|
|
it is unspecified when or how often this function is called. The use of hint
|
|
is unspecified, but intended as an aid to locality if an implementation so
|
|
desires.</p>
|
|
</blockquote>
|
|
<p>In [lib.char.traits.require] 21.1.1, paragraph 1: replace:</p>
|
|
<blockquote>
|
|
<p>In Table 37, X denotes a Traits class defining types and functions for the
|
|
character container type CharT; c and d denote values of type CharT; p and q
|
|
denote values of type const CharT*; s denotes a value of type CharT*; n, i and
|
|
j denote values of type size_t; e and f denote values of type X::int_type; pos
|
|
denotes a value of type X::pos_type; and state denotes a value of type X::state_type.</p>
|
|
</blockquote>
|
|
<p>by:</p>
|
|
<blockquote>
|
|
<p>In Table 37, X denotes a Traits class defining types and functions for the
|
|
character container type CharT; c and d denote values of type CharT; p and q
|
|
denote values of type const CharT*; s denotes a value of type CharT*; n, i and
|
|
j denote values of type std::size_t; e and f denote values of type X::int_type;
|
|
pos denotes a value of type X::pos_type; and state denotes a value of type X::state_type.</p>
|
|
</blockquote>
|
|
<p>In [lib.char.traits.require] 21.1.1, table 37: replace the return type of
|
|
X::length(p): "size_t" by "std::size_t".</p>
|
|
<p> In [lib.std.iterator.tags] 24.3.3, paragraph 2: replace:<br>
|
|
typedef ptrdiff_t difference_type;<br>
|
|
by:<br>
|
|
typedef std::ptrdiff_t difference_type;</p>
|
|
<p> In [lib.locale.ctype] 22.2.1.1 put namespace std { ...} around the declaration of template <class charT> class ctype.<br>
|
|
<br>
|
|
In [lib.iterator.traits] 24.3.1, paragraph 2 put namespace std { ...} around the declaration of:<br>
|
|
<br>
|
|
template<class Iterator> struct iterator_traits<br>
|
|
template<class T> struct iterator_traits<T*><br>
|
|
template<class T> struct iterator_traits<const T*></p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>The LWG believes correcting names like <tt>size_t</tt> and
|
|
<tt>ptrdiff_t</tt> to <tt>std::size_t</tt> and <tt>std::ptrdiff_t</tt>
|
|
to be essentially editorial. There there can't be another size_t or
|
|
ptrdiff_t meant anyway because, according to 17.4.3.1.4 ,</p>
|
|
|
|
<blockquote>
|
|
For each type T from the Standard C library, the types ::T and std::T
|
|
are reserved to the implementation and, when defined, ::T shall be
|
|
identical to std::T.
|
|
</blockquote>
|
|
|
|
<p>The issue is treated as a Defect Report to make explicit the Project
|
|
Editor's authority to make this change.</p>
|
|
|
|
<p><i>[Post-Tokyo: Nico Josuttis provided the above wording at the
|
|
request of the LWG.]</i></p>
|
|
|
|
<p><i>[Toronto: This is tangentially related to issue <a href="lwg-active.html#229">229</a>, but only tangentially: the intent of this issue is to
|
|
address use of the name <tt>size_t</tt> in contexts outside of
|
|
namespace std, such as in the description of <tt>::operator new</tt>.
|
|
The proposed changes should be reviewed to make sure they are
|
|
correct.]</i></p>
|
|
|
|
<p><i>[pre-Copenhagen: Nico has reviewed the changes and believes
|
|
them to be correct.]</i></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>
|
|
<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 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 ) that could ever meaningfully be passed to X::allocate</p>
|
|
|
|
<p>
|
|
Change 23.1 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 ) 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 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#Review">Review</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 , 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 , 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 :</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 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 .) The name of this member variable is shown for
|
|
exposition only. <i>--end note</i>]
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Tokyo: The LWG reformulated the question purely in terms of
|
|
iterators. The answer to the question is "no, pointers and references
|
|
don't remain valid after iterator destruction." PJP explained that
|
|
implementors use considerable care to avoid such ephemeral pointers and
|
|
references. Several LWG members said that they thought that the standard
|
|
did not actually specify the lifetime of pointers and references obtained from
|
|
iterators, except possibly input iterators.]</i></p>
|
|
|
|
<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: Andy Koenig pointed out that it is possible to
|
|
rewrite reverse_iterator so that it no longer makes this assumption.
|
|
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, then
|
|
other changes in reverse_iterator will be necessary.]</i></p>
|
|
<hr>
|
|
<a name="200"><h3>200. Forward iterator requirements don't allow constant iterators</h3></a><p>
|
|
<b>Section:</b> 24.1.3 <a href="lib-iterators.html#lib.forward.iterators"> [lib.forward.iterators]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</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, change the <b>return type</b> column for <tt>*a</tt>
|
|
from "<tt>T&</tt>" to "<tt>T&</tt> if
|
|
<tt>X</tt> is mutable, otherwise <tt>const T&</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>
|
|
<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#Open">Open</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>Options:</p>
|
|
<blockquote>
|
|
<p> 1. Impose an explicit requirement that the predicate be an
|
|
equivalence relation. </p>
|
|
<p> 2. Drop the word "equal" from the description to make it clear that
|
|
the intent is to compare pairs of adjacent elements, and
|
|
change pred(*i, *(i - 1)) to pred(*(i - 1), i).</p>
|
|
<p> 3. Change the effects to:</p>
|
|
<blockquote>
|
|
Effects: Eliminates all but the first element e from
|
|
every consecutive group of elements referred to by the
|
|
iterator i in the range [first, last) for which the
|
|
following corresponding conditions hold: e == *i or
|
|
pred(e,*i) != false.
|
|
</blockquote>
|
|
</blockquote>
|
|
<p>A LWG member, Nico Josuttis, comments:</p>
|
|
<p>First, I agree that the current wording is simply wrong. However, to follow
|
|
all [known] current implementations I propose [option 3 above].</p>
|
|
|
|
<p><i>[ Tokyo: The issue was discussed at length without reaching
|
|
consensus. Straw vote: Option 1 - preferred by 2 people. Option 2 -
|
|
preferred by 0 people. Option 3 - preferred by 3 people. Many
|
|
abstentions. ]</i></p>
|
|
|
|
<p><i>[Copenhagen: There was some support for all options. The option
|
|
with the least support was 1 (one person in favor), and the option
|
|
with the most support was 2 (seven in favor). One person was strongly
|
|
opposed to option 1, and one person was strongly opposed to the
|
|
variation on option 2 in which the order of arguments would remain
|
|
pred(*i, *(i - 1)).]</i></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 :</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 ).</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>
|
|
<hr>
|
|
<a name="228"><h3>228. Incorrect specification of "..._byname" facets</h3></a><p>
|
|
<b>Section:</b> 22.2 <a href="lib-locales.html#lib.locale.categories"> [lib.locale.categories]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Dietmar Kühl <b>Date:</b> 20 Apr 2000</p>
|
|
<p>The sections 22.2.1.2 , 22.2.1.4 ,
|
|
22.2.1.6 , 22.2.3.2 , 22.2.4.2 , 22.2.5.4 , 22.2.6.4 , and 22.2.7.2 overspecify the
|
|
definitions of the "..._byname" classes by listing a bunch
|
|
of virtual functions. At the same time, no semantics of these
|
|
functions are defined. Real implementations do not define these
|
|
functions because the functional part of the facets is actually
|
|
implemented in the corresponding base classes and the constructor of
|
|
the "..._byname" version just provides suitable date used by
|
|
these implementations. For example, the 'numpunct' methods just return
|
|
values from a struct. The base class uses a statically initialized
|
|
struct while the derived version reads the contents of this struct
|
|
from a table. However, no virtual function is defined in
|
|
'numpunct_byname'.</p>
|
|
|
|
<p>For most classes this does not impose a problem but specifically
|
|
for 'ctype' it does: The specialization for 'ctype_byname<char>'
|
|
is required because otherwise the semantics would change due to the
|
|
virtual functions defined in the general version for 'ctype_byname':
|
|
In 'ctype<char>' the method 'do_is()' is not virtual but it is
|
|
made virtual in both 'ctype<cT>' and 'ctype_byname<cT>'.
|
|
Thus, a class derived from 'ctype_byname<char>' can tell whether
|
|
this class is specialized or not under the current specification:
|
|
Without the specialization, 'do_is()' is virtual while with
|
|
specialization it is not virtual.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p> Change section 22.2.1.2 (lib.locale.ctype.byname) to become:</p>
|
|
<pre> namespace std {
|
|
template <class charT>
|
|
class ctype_byname : public ctype<charT> {
|
|
public:
|
|
typedef ctype<charT>::mask mask;
|
|
explicit ctype_byname(const char*, size_t refs = 0);
|
|
protected:
|
|
~ctype_byname(); // virtual
|
|
};
|
|
}</pre>
|
|
<p> Change section 22.2.1.6 (lib.locale.codecvt.byname) to become:</p>
|
|
<pre> namespace std {
|
|
template <class internT, class externT, class stateT>
|
|
class codecvt_byname : public codecvt<internT, externT, stateT> {
|
|
public:
|
|
explicit codecvt_byname(const char*, size_t refs = 0);
|
|
protected:
|
|
~codecvt_byname(); // virtual
|
|
};
|
|
}
|
|
</pre>
|
|
<p> Change section 22.2.3.2 (lib.locale.numpunct.byname) to become:</p>
|
|
<pre> namespace std {
|
|
template <class charT>
|
|
class numpunct_byname : public numpunct<charT> {
|
|
// this class is specialized for char and wchar_t.
|
|
public:
|
|
typedef charT char_type;
|
|
typedef basic_string<charT> string_type;
|
|
explicit numpunct_byname(const char*, size_t refs = 0);
|
|
protected:
|
|
~numpunct_byname(); // virtual
|
|
};
|
|
}</pre>
|
|
<p> Change section 22.2.4.2 (lib.locale.collate.byname) to become:</p>
|
|
<pre> namespace std {
|
|
template <class charT>
|
|
class collate_byname : public collate<charT> {
|
|
public:
|
|
typedef basic_string<charT> string_type;
|
|
explicit collate_byname(const char*, size_t refs = 0);
|
|
protected:
|
|
~collate_byname(); // virtual
|
|
};
|
|
}</pre>
|
|
<p> Change section 22.2.5.2 (lib.locale.time.get.byname) to become:</p>
|
|
<pre> namespace std {
|
|
template <class charT, class InputIterator = istreambuf_iterator<charT> >
|
|
class time_get_byname : public time_get<charT, InputIterator> {
|
|
public:
|
|
typedef time_base::dateorder dateorder;
|
|
typedef InputIterator iter_type</pre>
|
|
<pre> explicit time_get_byname(const char*, size_t refs = 0);
|
|
protected:
|
|
~time_get_byname(); // virtual
|
|
};
|
|
}</pre>
|
|
<p> Change section 22.2.5.4 (lib.locale.time.put.byname) to become:</p>
|
|
<pre> namespace std {
|
|
template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
|
|
class time_put_byname : public time_put<charT, OutputIterator>
|
|
{
|
|
public:
|
|
typedef charT char_type;
|
|
typedef OutputIterator iter_type;</pre>
|
|
<pre> explicit time_put_byname(const char*, size_t refs = 0);
|
|
protected:
|
|
~time_put_byname(); // virtual
|
|
};
|
|
}"</pre>
|
|
<p> Change section 22.2.6.4 (lib.locale.moneypunct.byname) to become:</p>
|
|
<pre> namespace std {
|
|
template <class charT, bool Intl = false>
|
|
class moneypunct_byname : public moneypunct<charT, Intl> {
|
|
public:
|
|
typedef money_base::pattern pattern;
|
|
typedef basic_string<charT> string_type;</pre>
|
|
<pre> explicit moneypunct_byname(const char*, size_t refs = 0);
|
|
protected:
|
|
~moneypunct_byname(); // virtual
|
|
};
|
|
}</pre>
|
|
<p> Change section 22.2.7.2 (lib.locale.messages.byname) to become:</p>
|
|
<pre> namespace std {
|
|
template <class charT>
|
|
class messages_byname : public messages<charT> {
|
|
public:
|
|
typedef messages_base::catalog catalog;
|
|
typedef basic_string<charT> string_type;</pre>
|
|
<pre> explicit messages_byname(const char*, size_t refs = 0);
|
|
protected:
|
|
~messages_byname(); // virtual
|
|
};
|
|
}</pre>
|
|
<p>Remove section 22.2.1.4 completely (because in
|
|
this case only those members are defined to be virtual which are
|
|
defined to be virtual in 'ctype<cT>'.)</p>
|
|
|
|
<p><i>[Post-Tokyo: Dietmar Kühl submitted this issue at the request of
|
|
the LWG to solve the underlying problems raised by issue <a href="lwg-closed.html#138">138</a>.]</i></p>
|
|
|
|
<p><i>[Copenhagen: proposed resolution was revised slightly, to remove
|
|
three last virtual functions from <tt>messages_byname</tt>.]</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-active.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="230"><h3>230. Assignable specified without also specifying CopyConstructible</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#Ready">Ready</a> <b>Submitter:</b> Beman Dawes <b>Date:</b> 26 Apr 2000</p>
|
|
<p>Issue <a href="lwg-defects.html#227">227</a> identified an instance (std::swap) where
|
|
Assignable was specified without also specifying
|
|
CopyConstructible. The LWG asked that the standard be searched to
|
|
determine if the same defect existed elsewhere.</p>
|
|
|
|
<p>There are a number of places (see proposed resolution below) where
|
|
Assignable is specified without also specifying
|
|
CopyConstructible. There are also several cases where both are
|
|
specified. For example, 26.4.1 .</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 23.1 table 65 for value_type:
|
|
change "T is Assignable" to "T is CopyConstructible and
|
|
Assignable"
|
|
</p>
|
|
|
|
<p>In 23.1.2 table 69 X::key_type; change
|
|
"Key is Assignable" to "Key is
|
|
CopyConstructible and Assignable"<br>
|
|
</p>
|
|
|
|
<p>In 24.1.2 paragraph 1, change:
|
|
</p>
|
|
<blockquote>
|
|
<p> A class or a built-in type X satisfies the requirements of an
|
|
output iterator if X is an Assignable type (23.1) and also the
|
|
following expressions are valid, as shown in Table 73:
|
|
</p>
|
|
</blockquote>
|
|
<p>to:
|
|
</p>
|
|
<blockquote>
|
|
<p> A class or a built-in type X satisfies the requirements of an
|
|
output iterator if X is a CopyConstructible (20.1.3) and Assignable
|
|
type (23.1) and also the following expressions are valid, as shown in
|
|
Table 73:
|
|
</p>
|
|
</blockquote>
|
|
|
|
<p><i>[Post-Tokyo: Beman Dawes submitted this issue at the request of
|
|
the LWG. He asks that the 25.2.4 and 25.2.5 changes be studied carefully, as it is not clear that
|
|
CopyConstructible is really a requirement and may be
|
|
overspecification.]</i></p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>The original proposed resolution also included changes to input
|
|
iterator, fill, and replace. The LWG believes that those changes are
|
|
not necessary. The LWG considered some blanket statement, where an
|
|
Assignable type was also required to be Copy Constructible, but
|
|
decided against this because fill and replace really don't require the
|
|
Copy Constructible property.</p>
|
|
<hr>
|
|
<a name="231"><h3>231. Precision in iostream?</h3></a><p>
|
|
<b>Section:</b> 22.2.2.2.2 <a href="lib-locales.html#lib.facet.num.put.virtuals"> [lib.facet.num.put.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#Review">Review</a> <b>Submitter:</b> James Kanze, Stephen Clamage <b>Date:</b> 25 Apr 2000</p>
|
|
<p>What is the following program supposed to output?</p>
|
|
<pre>#include <iostream>
|
|
|
|
int
|
|
main()
|
|
{
|
|
std::cout.setf( std::ios::scientific , std::ios::floatfield ) ;
|
|
std::cout.precision( 0 ) ;
|
|
std::cout << 1.23 << '\n' ;
|
|
return 0 ;
|
|
}</pre>
|
|
<p>From my C experience, I would expect "1e+00"; this is what
|
|
<tt>printf("%.0e" , 1.23 );</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 , 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="232"><h3>232. "depends" poorly defined in 17.4.3.1</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#Ready">Ready</a> <b>Submitter:</b> Peter Dimov <b>Date:</b> 18 Apr 2000</p>
|
|
<p>17.4.3.1/1 uses the term "depends" to limit the set of allowed
|
|
specializations of standard templates to those that "depend on a
|
|
user-defined name of external linkage."</p>
|
|
<p>This term, however, is not adequately defined, making it possible to
|
|
construct a specialization that is, I believe, technically legal according to
|
|
17.4.3.1/1, but that specializes a standard template for a built-in type such as
|
|
'int'.</p>
|
|
<p>The following code demonstrates the problem:</p>
|
|
<blockquote>
|
|
<pre>#include <algorithm></pre>
|
|
<pre>template<class T> struct X
|
|
{
|
|
typedef T type;
|
|
};</pre>
|
|
<pre>namespace std
|
|
{
|
|
template<> void swap(::X<int>::type& i, ::X<int>::type& j);
|
|
}</pre>
|
|
</blockquote>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change "user-defined name" to "user-defined
|
|
type".</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>This terminology is used in section 2.5.2 and 4.1.1 of <i>The C++
|
|
Programming Language</i>. It disallows the example in the issue,
|
|
since the underlying type itself is not user-defined. The only
|
|
possible problem I can see is for non-type templates, but there's no
|
|
possible way for a user to come up with a specialization for bitset,
|
|
for example, that might not have already been specialized by the
|
|
implementor?</p>
|
|
|
|
<p><i>[Toronto: this may be related to issue <a href="lwg-active.html#120">120</a>.]</i></p>
|
|
|
|
<p><i>[post-Toronto: Judy provided the above proposed resolution and
|
|
rationale.]</i></p>
|
|
<hr>
|
|
<a name="233"><h3>233. Insertion hints in associative containers</h3></a><p>
|
|
<b>Section:</b> 23.1.2 <a href="lib-containers.html#lib.associative.reqmts"> [lib.associative.reqmts]</a> <b>Status:</b> <a href="lwg-active.html#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>Proposed resolution:</b></p>
|
|
|
|
<p>
|
|
General Idea (Andrew Koenig):
|
|
t is inserted at the point closest to (the point immediately
|
|
ahead of) p. That would give the user a way of controlling the order
|
|
in which elements appear that have equal keys. Doing so would be
|
|
particularly easy in two cases that I suspect are common:
|
|
</p>
|
|
<pre>
|
|
mm.insert(mm.begin(), t); // inserts as first element of set of equal keys
|
|
mm.insert(mm.end(), t); // inserts as last element of set of equal keys
|
|
</pre>
|
|
|
|
<p>
|
|
These examples would allow t to be inserted at the beginning and end,
|
|
respectively, of the set of elements with the same key as t.
|
|
</p>
|
|
|
|
<p>
|
|
assertion/note/pre/postcondition in table 69<br>
|
|
Change:
|
|
</p>
|
|
<blockquote>
|
|
iterator p is a hint pointing to where the insert should start to search.
|
|
</blockquote>
|
|
<p>To:</p>
|
|
<blockquote>
|
|
if t is inserted, p is used as follows: insert t right before p
|
|
if possible; otherwise, if p is equal to a.end(), or if the key value
|
|
of t is greater than the key value of *p, t is inserted just before
|
|
a.lowerbound(the key value of t); otherwise, t is inserted right
|
|
before a.upperbound(the key value of t).
|
|
</blockquote>
|
|
<p>complexity:<br>
|
|
Change:</p>
|
|
<blockquote>right after p</blockquote>
|
|
<p>To:</p>
|
|
<blockquote>right before p</blockquote>
|
|
|
|
<p>
|
|
Thus making:<br>
|
|
assertion/note/pre/postcondition:
|
|
</p>
|
|
<blockquote>
|
|
inserts t if and only if there is no element with key equivalent to
|
|
the key of t in containers with unique keys; always inserts t in
|
|
containers with equivalent keys. always returns the iterator pointing
|
|
to the element with key equivalent to the key of t.
|
|
if t is inserted, p is used as follows: insert t right before p
|
|
if possible; otherwise, if p is equal to a.end(), or if the key value
|
|
of t is greater than the key value of *p, t is inserted just before
|
|
a.lowerbound(the key value of t); otherwise, t is inserted right
|
|
before a.upperbound(the key value of t).
|
|
<br>NON-NORMATIVE FOOTNOTE:
|
|
| This gives the user a way of controlling the order
|
|
| in which elements appear that have equal keys. Doing this is
|
|
| particularly easy in two common cases:
|
|
<pre>
|
|
| mm.insert(mm.begin(), t); // inserts as first element of set of equal keys
|
|
| mm.insert(mm.end(), t); // inserts as last element of set of equal keys
|
|
</pre>
|
|
<br>END-FOOTNOTE
|
|
</blockquote>
|
|
|
|
<p>complexity:</p>
|
|
<blockquote>
|
|
logarithmic in general, but amortized constant if t is inserted right
|
|
before 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>
|
|
|
|
<hr>
|
|
<a name="235"><h3>235. No specification of default ctor for reverse_iterator</h3></a><p>
|
|
<b>Section:</b> 24.4.1.1 <a href="lib-iterators.html#lib.reverse.iterator"> [lib.reverse.iterator]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Dietmar Kühl <b>Date:</b> 24 Apr 2000</p>
|
|
<p>The declaration of <tt>reverse_iterator</tt> lists a default
|
|
constructor. However, no specification is given what this constructor
|
|
should do.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In section 24.4.1.3.1 add the following
|
|
paragraph:</p>
|
|
<blockquote>
|
|
<p><tt>reverse_iterator()</tt></p>
|
|
|
|
<p>Default initializes <tt>current</tt>. Iterator operations
|
|
applied to the resulting iterator have defined behavior if and
|
|
only if the corresponding operations are defined on a default
|
|
constructed iterator of type <tt>Iterator</tt>.</p>
|
|
</blockquote>
|
|
<p><i>[pre-Copenhagen: Dietmar provide wording for proposed
|
|
resolution.]</i></p>
|
|
<hr>
|
|
<a name="238"><h3>238. Contradictory results of stringbuf initialization.</h3></a><p>
|
|
<b>Section:</b> 27.7.1.1 <a href="lib-iostreams.html#lib.stringbuf.cons"> [lib.stringbuf.cons]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Dietmar Kühl <b>Date:</b> 11 May 2000</p>
|
|
<p>In 27.7.1.1 paragraph 4 the results of calling the constructor of
|
|
'basic_stringbuf' are said to be <tt>str() == str</tt>. This is fine
|
|
that far but consider this code:</p>
|
|
|
|
<pre>
|
|
std::basic_stringbuf<char> sbuf("hello, world", std::ios_base::openmode(0));
|
|
std::cout << "'" << sbuf.str() << "'\n";
|
|
</pre>
|
|
|
|
<p>Paragraph 3 of 27.7.1.1 basically says that in this case neither
|
|
the output sequence nor the input sequence is initialized and
|
|
paragraph 2 of 27.7.1.2 basically says that <tt>str()</tt> either
|
|
returns the input or the output sequence. None of them is initialized,
|
|
ie. both are empty, in which case the return from <tt>str()</tt> is
|
|
defined to be <tt>basic_string<cT>()</tt>.</p>
|
|
|
|
<p>However, probably only test cases in some testsuites will detect this
|
|
"problem"...</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Remove 27.7.1.1 paragraph 4.</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>We could fix 27.7.1.1 paragraph 4, but there would be no point. If
|
|
we fixed it, it would say just the same thing as text that's already
|
|
in the standard.</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#Open">Open</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 to:</p>
|
|
|
|
<blockquote>Complexity: Exactly last - first - 1 applications of the
|
|
corresponding predicate.</blockquote>
|
|
|
|
<p><i>[Toronto: This is related to issue <a href="lwg-active.html#202">202</a>. We can't
|
|
specify <tt>unique</tt>'s complexity until we decide what
|
|
<tt>unique</tt> is supposed to do.]</i></p>
|
|
<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#Review">Review</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 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#Ready">Ready</a> <b>Submitter:</b> Angelika Langer <b>Date:</b> May 15 2000</p>
|
|
|
|
<p>Some popular implementations of unique_copy() create temporary
|
|
copies of values in the input sequence, at least if the input iterator
|
|
is a pointer. Such an implementation is built on the assumption that
|
|
the value type is CopyConstructible and Assignable.</p>
|
|
|
|
<p>It is common practice in the standard that algorithms explicitly
|
|
specify any additional requirements that they impose on any of the
|
|
types used by the algorithm. An example of an algorithm that creates
|
|
temporary copies and correctly specifies the additional requirements
|
|
is accumulate(), 26.4.1 .</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 is valid.
|
|
</blockquote>
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
Creating temporary copies is unavoidable, since the arguments may be
|
|
input iterators; this implies that the value type must be copy
|
|
constructible. However, we don't need to say this explicitly; it's
|
|
already implied by table 72 in 24.1.1. We don't precisely want to say
|
|
that the input iterator's value type <tt>T</tt> must be assignable,
|
|
because we never quite use that property. We assign through the
|
|
output iterator. The output iterator might have a different value
|
|
type, or no value type; it might not use <tt>T</tt>'s assignment
|
|
operator. If it's an <tt>ostream_iterator</tt>, for example, then
|
|
we'll use <tt>T</tt>'s operator<< but not its assignment
|
|
operator.
|
|
</p>
|
|
<hr>
|
|
<a name="242"><h3>242. Side effects of function objects</h3></a><p>
|
|
<b>Section:</b> 25.2.3 <a href="lib-algorithms.html#lib.alg.transform"> [lib.alg.transform]</a>, 26.4 <a href="lib-numerics.html#lib.numeric.ops"> [lib.numeric.ops]</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 algorithms transform(), accumulate(), inner_product(),
|
|
partial_sum(), and adjacent_difference() require that the function
|
|
object supplied to them shall not have any side effects.</p>
|
|
|
|
<p>The standard defines a side effect in 1.9 as:</p>
|
|
<blockquote>-7- Accessing an object designated by a volatile lvalue (basic.lval),
|
|
modifying an object, calling a library I/O function, or calling a function
|
|
that does any of those operations are all side effects, which are changes
|
|
in the state of the execution environment.</blockquote>
|
|
|
|
<p>As a consequence, the function call operator of a function object supplied
|
|
to any of the algorithms listed above cannot modify data members, cannot
|
|
invoke any function that has a side effect, and cannot even create and
|
|
modify temporary objects. It is difficult to imagine a function object
|
|
that is still useful under these severe limitations. For instance, any
|
|
non-trivial transformator supplied to transform() might involve creation
|
|
and modification of temporaries, which is prohibited according to the current
|
|
wording of the standard.</p>
|
|
|
|
<p>On the other hand, popular implementations of these algorithms exhibit
|
|
uniform and predictable behavior when invoked with a side-effect-producing
|
|
function objects. It looks like the strong requirement is not needed for
|
|
efficient implementation of these algorithms.</p>
|
|
|
|
<p>The requirement of side-effect-free function objects could be
|
|
replaced by a more relaxed basic requirement (which would hold for all
|
|
function objects supplied to any algorithm in the standard library):</p>
|
|
<blockquote>A function objects supplied to an algorithm shall not invalidate
|
|
any iterator or sequence that is used by the algorithm. Invalidation of
|
|
the sequence includes destruction of the sorting order if the algorithm
|
|
relies on the sorting order (see section 25.3 - Sorting and related operations
|
|
[lib.alg.sorting]).</blockquote>
|
|
|
|
<p>I can't judge whether it is intended that the function objects supplied
|
|
to transform(), accumulate(), inner_product(), partial_sum(), or adjacent_difference()
|
|
shall not modify sequence elements through dereferenced iterators.</p>
|
|
|
|
<p>It is debatable whether this issue is a defect or a change request.
|
|
Since the consequences for user-supplied function objects are drastic and
|
|
limit the usefulness of the algorithms significantly I would consider it
|
|
a defect.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p><i>Things to notice about these changes:</i></p>
|
|
|
|
<ol>
|
|
<li> <i>The fully-closed ("[]" as opposed to half-closed "[)" ranges
|
|
are intentional. we want to prevent side-effects from
|
|
invalidating the end iterators.</i>
|
|
</li>
|
|
|
|
<li> <i>That has the unintentional side-effect of prohibiting
|
|
modification of the end element as a side-effect. This could
|
|
conceivably be significant in some cases.</i>
|
|
</li>
|
|
|
|
<li> <i>The wording also prevents side-effects from modifying elements
|
|
of the output sequence. I can't imagine why anyone would want
|
|
to do this, but it is arguably a restriction that implementors
|
|
don't need to place on users.</i>
|
|
</li>
|
|
|
|
<li> <i>Lifting the restrictions imposed in #2 and #3 above is possible
|
|
and simple, but would require more verbiage.</i>
|
|
</li>
|
|
</ol>
|
|
|
|
<p>Change 25.2.3/2 from:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: op and binary_op shall not have any side effects.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: in the ranges [first1, last1], [first2, first2 +
|
|
(last1 - first1)] and [result, result + (last1- first1)], op and
|
|
binary_op shall neither modify elements nor invalidate iterators or
|
|
subranges.
|
|
[Footnote: The use of fully closed ranges is intentional --end footnote]
|
|
</blockquote>
|
|
|
|
|
|
<p>Change 25.2.3/2 from:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: op and binary_op shall not have any side effects.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: op and binary_op shall not invalidate iterators or
|
|
subranges, or modify elements in the ranges [first1, last1],
|
|
[first2, first2 + (last1 - first1)], and [result, result + (last1
|
|
- first1)].
|
|
[Footnote: The use of fully closed ranges is intentional --end footnote]
|
|
</blockquote>
|
|
|
|
|
|
<p>Change 26.4.1/2 from:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: T must meet the requirements of CopyConstructible
|
|
(lib.copyconstructible) and Assignable (lib.container.requirements)
|
|
types. binary_op shall not cause side effects.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: T must meet the requirements of CopyConstructible
|
|
(lib.copyconstructible) and Assignable
|
|
(lib.container.requirements) types. In the range [first, last],
|
|
binary_op shall neither modify elements nor invalidate iterators
|
|
or subranges.
|
|
[Footnote: The use of a fully closed range is intentional --end footnote]
|
|
</blockquote>
|
|
|
|
<p>Change 26.4.2/2 from:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: T must meet the requirements of CopyConstructible
|
|
(lib.copyconstructible) and Assignable (lib.container.requirements)
|
|
types. binary_op1 and binary_op2 shall not cause side effects.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: T must meet the requirements of CopyConstructible
|
|
(lib.copyconstructible) and Assignable (lib.container.requirements)
|
|
types. In the ranges [first, last] and [first2, first2 + (last -
|
|
first)], binary_op1 and binary_op2 shall neither modify elements
|
|
nor invalidate iterators or subranges.
|
|
[Footnote: The use of fully closed ranges is intentional --end footnote]
|
|
</blockquote>
|
|
|
|
|
|
<p>Change 26.4.3/4 from:</p>
|
|
|
|
<blockquote>
|
|
-4- Requires: binary_op is expected not to have any side effects.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-4- Requires: In the ranges [first, last] and [result, result +
|
|
(last - first)], binary_op shall neither modify elements nor
|
|
invalidate iterators or subranges.
|
|
[Footnote: The use of fully closed ranges is intentional --end footnote]
|
|
</blockquote>
|
|
|
|
<p>Change 26.4.4/2 from:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: binary_op shall not have any side effects.
|
|
</blockquote>
|
|
|
|
<p>to:</p>
|
|
|
|
<blockquote>
|
|
-2- Requires: In the ranges [first, last] and [result, result +
|
|
(last - first)], binary_op shall neither modify elements nor
|
|
invalidate iterators or subranges.
|
|
[Footnote: The use of fully closed ranges is intentional --end footnote]
|
|
</blockquote>
|
|
|
|
<p><i>[Toronto: Dave Abrahams supplied wording.]</i></p>
|
|
|
|
<p><i>[Copenhagen: Proposed resolution was modified slightly. Matt
|
|
added footnotes pointing out that the use of closed ranges was
|
|
intentional.]</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 ,
|
|
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="250"><h3>250. splicing invalidates iterators</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> Brian Parker <b>Date:</b> 14 Jul 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>
|
|
This is unnecessary and defeats an important feature of splice. In
|
|
fact, the SGI STL guarantees that iterators to <tt>x</tt> remain valid
|
|
after <tt>splice</tt>.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>Add a footnote to 23.2.2.4 , paragraph 1:</p>
|
|
<blockquote>
|
|
[<i>Footnote:</i> As specified in 20.1.5 , paragraphs
|
|
4-5, the semantics described in this clause applies only to the case
|
|
where allocators compare equal. --end footnote]
|
|
</blockquote>
|
|
|
|
<p>In 23.2.2.4 , replace paragraph 4 with:</p>
|
|
<blockquote>
|
|
Effects: Inserts the contents of x before position and x becomes
|
|
empty. Pointers and references to the moved elements of x now refer to
|
|
those same elements but as members of *this. Iterators referring to the
|
|
moved elements will continue to refer to their elements, but they now
|
|
behave as iterators into *this, not into x.
|
|
</blockquote>
|
|
|
|
<p>In 23.2.2.4 , replace paragraph 7 with:</p>
|
|
<blockquote>
|
|
Effects: Inserts an element pointed to by i from list x before
|
|
position and removes the element from x. The result is unchanged if
|
|
position == i or position == ++i. Pointers and references to *i continue
|
|
to refer to this same element but as a member of *this. Iterators to *i
|
|
(including i itself) continue to refer to the same element, but now
|
|
behave as iterators into *this, not into x.
|
|
</blockquote>
|
|
|
|
<p>In 23.2.2.4 , replace paragraph 12 with:</p>
|
|
<blockquote>
|
|
Requires: [first, last) is a valid range in x. The result is
|
|
undefined if position is an iterator in the range [first, last).
|
|
Pointers and references to the moved elements of x now refer to those
|
|
same elements but as members of *this. Iterators referring to the moved
|
|
elements will continue to refer to their elements, but they now behave as
|
|
iterators into *this, not into x.
|
|
</blockquote>
|
|
|
|
<p><i>[pre-Copenhagen: Howard provided wording.]</i></p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>The original proposed resolution said that iterators and references
|
|
would remain "valid". The new proposed resolution clarifies what that
|
|
means. Note that this only applies to the case of equal allocators.
|
|
From 20.1.5 paragraph 4, the behavior of list when
|
|
allocators compare nonequal is outside the scope of the standard.</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#Open">Open</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>
|
|
Adopt section 2 of 00-0023/N1246. Sections 1 and 5 of that paper have
|
|
already been classified as "Request for Extension". Sections
|
|
3 and 4 are reasonable generalizations of section 2, but they do not
|
|
resolve an obvious inconsistency in the standard.
|
|
</p>
|
|
|
|
<p><i>[Toronto: it is agreed that there is a defect. A full
|
|
discussion, and an attempt at fixing the defect, should wait until we
|
|
can hear from valarray experts.]</i></p>
|
|
<hr>
|
|
<a name="254"><h3>254. Exception types in clause 19 are constructed from <tt>std::string</tt>
|
|
</h3></a><p>
|
|
<b>Section:</b> 19.1 <a href="lib-diagnostics.html#lib.std.exceptions"> [lib.std.exceptions]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 01 Aug 2000</p>
|
|
<p>
|
|
Many of the standard exception types which implementations are
|
|
required to throw are constructed with a const std::string&
|
|
parameter. For example:
|
|
</p>
|
|
|
|
<pre>
|
|
19.1.5 Class out_of_range [lib.out.of.range]
|
|
namespace std {
|
|
class out_of_range : public logic_error {
|
|
public:
|
|
explicit out_of_range(const string& what_arg);
|
|
};
|
|
}
|
|
|
|
1 The class out_of_range defines the type of objects thrown as excep-
|
|
tions to report an argument value not in its expected range.
|
|
|
|
out_of_range(const string& what_arg);
|
|
|
|
Effects:
|
|
Constructs an object of class out_of_range.
|
|
Postcondition:
|
|
strcmp(what(), what_arg.c_str()) == 0.
|
|
</pre>
|
|
|
|
<p>
|
|
There are at least two problems with this:
|
|
</p>
|
|
<ol>
|
|
<li>A program which is low on memory may end up throwing
|
|
std::bad_alloc instead of out_of_range because memory runs out while
|
|
constructing the exception object.</li>
|
|
<li>An obvious implementation which stores a std::string data member
|
|
may end up invoking terminate() during exception unwinding because the
|
|
exception object allocates memory (or rather fails to) as it is being
|
|
copied.</li>
|
|
</ol>
|
|
|
|
<p>
|
|
There may be no cure for (1) other than changing the interface to
|
|
out_of_range, though one could reasonably argue that (1) is not a
|
|
defect. Personally I don't care that much if out-of-memory is reported
|
|
when I only have 20 bytes left, in the case when out_of_range would
|
|
have been reported. People who use exception-specifications might care
|
|
a lot, though.
|
|
</p>
|
|
|
|
<p>
|
|
There is a cure for (2), but it isn't completely obvious. I think a
|
|
note for implementors should be made in the standard. Avoiding
|
|
possible termination in this case shouldn't be left up to chance. The
|
|
cure is to use a reference-counted "string" implementation
|
|
in the exception object. I am not necessarily referring to a
|
|
std::string here; any simple reference-counting scheme for a NTBS
|
|
would do.
|
|
</p>
|
|
|
|
<p>
|
|
Further discussion, in email:
|
|
</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>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>
|
|
<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="259"><h3>259. <tt>basic_string::operator[]</tt> and const correctness</h3></a><p>
|
|
<b>Section:</b> 21.3.4 <a href="lib-strings.html#lib.string.access"> [lib.string.access]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Chris Newton <b>Date:</b> 27 Aug 2000</p>
|
|
<p>
|
|
<i>Paraphrased from a message that Chris Newton posted to comp.std.c++:</i>
|
|
</p>
|
|
|
|
<p>
|
|
The standard's description of <tt>basic_string<>::operator[]</tt>
|
|
seems to violate const correctness.
|
|
</p>
|
|
|
|
<p>
|
|
The standard (21.3.4/1) says that "If <tt>pos < size()</tt>,
|
|
returns <tt>data()[pos]</tt>." The types don't work. The
|
|
return value of <tt>data()</tt> is <tt>const charT*</tt>, but
|
|
<tt>operator[]</tt> has a non-const version whose return type is <tt>reference</tt>.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In section 21.3.4, paragraph 1, change
|
|
"<tt>data()[<i>pos</i>]</tt>" to "<tt>*(begin() +
|
|
<i>pos</i>)</tt>".
|
|
</p>
|
|
<hr>
|
|
<a name="264"><h3>264. Associative container <tt>insert(i, j)</tt> complexity requirements are not feasible.</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> John Potter <b>Date:</b> 07 Sep 2000</p>
|
|
<p>
|
|
Table 69 requires linear time if [i, j) is sorted. Sorted is necessary but not sufficient.
|
|
Consider inserting a sorted range of even integers into a set<int> containing the odd
|
|
integers in the same range.
|
|
</p>
|
|
|
|
<p><i>Related issue: <a href="lwg-closed.html#102">102</a></i></p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
In Table 69, in section 23.1.2, change the complexity clause for
|
|
insertion of a range from "N log(size() + N) (N is the distance
|
|
from i to j) in general; linear if [i, j) is sorted according to
|
|
value_comp()" to "N log(size() + N), where N is the distance
|
|
from i to j".
|
|
</p>
|
|
|
|
<p><i>[Copenhagen: Minor fix in proposed resolution: fixed unbalanced
|
|
parens in the revised wording.]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
Testing for valid insertions could be less efficient than simply
|
|
inserting the elements when the range is not both sorted and between
|
|
two adjacent existing elements; this could be a QOI issue.
|
|
</p>
|
|
|
|
<p>
|
|
The LWG considered two other options: (a) specifying that the
|
|
complexity was linear if [i, j) is sorted according to value_comp()
|
|
and between two adjacent existing elements; or (b) changing to
|
|
Klog(size() + N) + (N - K) (N is the distance from i to j and K is the
|
|
number of elements which do not insert immediately after the previous
|
|
element from [i, j) including the first). The LWG felt that, since
|
|
we can't guarantee linear time complexity whenever the range to be
|
|
inserted is sorted, it's more trouble than it's worth to say that it's
|
|
linear in some special cases.
|
|
</p>
|
|
<hr>
|
|
<a name="266"><h3>266. bad_exception::~bad_exception() missing Effects clause</h3></a><p>
|
|
<b>Section:</b> 18.6.2.1 <a href="lib-support.html#lib.bad.exception"> [lib.bad.exception]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 24 Sep 2000</p>
|
|
<p>
|
|
The synopsis for std::bad_exception lists the function ~bad_exception()
|
|
but there is no description of what the function does (the Effects
|
|
clause is missing).
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Remove the destructor from the class synopses of
|
|
<tt>bad_alloc</tt> (18.4.2.1 ),
|
|
<tt>bad_cast</tt> (18.5.2 ),
|
|
<tt>bad_typeid</tt> (18.5.3 ),
|
|
and <tt>bad_exception</tt> (18.6.2.1 ).
|
|
</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
This is a general problem with the exception classes in clause 18.
|
|
The proposed resolution is to remove the destructors from the class
|
|
synopses, rather than to document the destructors' behavior, because
|
|
removing them is more consistent with how exception classes are
|
|
described in clause 19.
|
|
</p>
|
|
<hr>
|
|
<a name="267"><h3>267. interaction of strstreambuf::overflow() and seekoff()</h3></a><p>
|
|
<b>Section:</b> D.7.1.3 <a href="future.html#depr.strstreambuf.virtuals"> [depr.strstreambuf.virtuals]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 5 Oct 2000</p>
|
|
<p>
|
|
It appears that the interaction of the strstreambuf members overflow()
|
|
and seekoff() can lead to undefined behavior in cases where defined
|
|
behavior could reasonably be expected. The following program
|
|
demonstrates this behavior:
|
|
</p>
|
|
|
|
<pre>
|
|
#include <strstream>
|
|
|
|
int main ()
|
|
{
|
|
std::strstreambuf sb;
|
|
sb.sputc ('c');
|
|
|
|
sb.pubseekoff (-1, std::ios::end, std::ios::in);
|
|
return !('c' == sb.sgetc ());
|
|
}
|
|
</pre>
|
|
|
|
<p>
|
|
D.7.1.1, p1 initializes strstreambuf with a call to basic_streambuf<>(),
|
|
which in turn sets all pointers to 0 in 27.5.2.1, p1.
|
|
</p>
|
|
|
|
<p>
|
|
27.5.2.2.5, p1 says that basic_streambuf<>::sputc(c) calls
|
|
overflow(traits::to_int_type(c)) if a write position isn't available (it
|
|
isn't due to the above).
|
|
</p>
|
|
|
|
<p>
|
|
D.7.1.3, p3 says that strstreambuf::overflow(off, ..., ios::in) makes at
|
|
least one write position available (i.e., it allows the function to make
|
|
any positive number of write positions available).
|
|
</p>
|
|
|
|
<p>
|
|
D.7.1.3, p13 computes newoff = seekhigh - eback(). In D.7.1, p4 we see
|
|
seekhigh = epptr() ? epptr() : egptr(), or seekhigh = epptr() in this
|
|
case. newoff is then epptr() - eback().
|
|
</p>
|
|
|
|
<p>
|
|
D.7.1.4, p14 sets gptr() so that gptr() == eback() + newoff + off, or
|
|
gptr() == epptr() + off holds.
|
|
</p>
|
|
|
|
<p>
|
|
If strstreambuf::overflow() made exactly one write position available
|
|
then gptr() will be set to just before epptr(), and the program will
|
|
return 0. Buf if the function made more than one write position
|
|
available, epptr() and gptr() will both point past pptr() and the
|
|
behavior of the program is undefined.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
|
|
<p>Change the last sentence of D.7.1 paragraph 4 from</p>
|
|
|
|
<blockquote>
|
|
Otherwise, seeklow equals gbeg and seekhigh is either pend, if
|
|
pend is not a null pointer, or gend.
|
|
</blockquote>
|
|
|
|
<p>to become</p>
|
|
|
|
<blockquote>
|
|
Otherwise, seeklow equals gbeg and seekhigh is either gend if
|
|
0 == pptr(), or pbase() + max where max is the maximum value of
|
|
pptr() - pbase() ever reached for this stream.
|
|
</blockquote>
|
|
|
|
<p><i>[
|
|
pre-Copenhagen: Dietmar provided wording for proposed resolution.
|
|
]</i></p>
|
|
|
|
<p><i>[
|
|
post-Copenhagen: Fixed a typo: proposed resolution said to fix
|
|
4.7.1, not D.7.1.
|
|
]</i></p>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>Note that this proposed resolution does not require an increase in
|
|
the layout of strstreambuf to maintain max: If overflow() is
|
|
implemented to make exactly one write position available, max ==
|
|
epptr() - pbase() always holds. However, if overflow() makes more than
|
|
one write position available, the number of additional character (or
|
|
some equivalent) has to be stored somewhere.</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#Review">Review</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 not 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 a non-negative 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).
|
|
</blockquote>
|
|
|
|
<p>
|
|
Optionally add the following to the end of the proposed text above,
|
|
which allows library implementors to make a small optimization at the
|
|
cost of slightly complexifying the standard text. The idea is that we
|
|
want to ensure that the partition point which defines the upper_bound
|
|
is no earlier in the sequence than the partion point which defines the
|
|
lower_bound, so that the implementor can do one of the searches over a
|
|
subrange:
|
|
</p>
|
|
|
|
<blockquote>
|
|
Also, for all elements e of [first, last), e < value implies
|
|
!(value < e) or comp(e, value) implies !comp(value, e)
|
|
</blockquote>
|
|
|
|
<p>Note also that if we don't add the above, the result of
|
|
equal_range() might be an invalid range.</p>
|
|
|
|
|
|
<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>
|
|
Note that the original text did not say whether the first element of
|
|
the return value was the beginning or end of the range, or something
|
|
else altogether. The proposed text is both more precise and general
|
|
enough to accomodate heterogeneous comparisons.
|
|
</p>
|
|
|
|
<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>[Dave Abrahams provided this wording]</i></p>
|
|
|
|
<hr>
|
|
<a name="271"><h3>271. basic_iostream missing typedefs</h3></a><p>
|
|
<b>Section:</b> 27.6.1.5 <a href="lib-iostreams.html#lib.iostreamclass"> [lib.iostreamclass]</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>
|
|
Class template basic_iostream has no typedefs. The typedefs it
|
|
inherits from its base classes can't be used, since (for example)
|
|
basic_iostream<T>::traits_type is ambiguous.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>Add the following to basic_iostream's class synopsis in
|
|
27.6.1.5 , immediately after <tt>public</tt>:</p>
|
|
|
|
<pre>
|
|
// types:
|
|
typedef charT char_type;
|
|
typedef typename traits::int_type int_type;
|
|
typedef typename traits::pos_type pos_type;
|
|
typedef typename traits::off_type off_type;
|
|
typedef traits traits_type;
|
|
</pre>
|
|
<hr>
|
|
<a name="272"><h3>272. Missing parentheses around subexpression</h3></a><p>
|
|
<b>Section:</b> 27.4.4.3 <a href="lib-iostreams.html#lib.iostate.flags"> [lib.iostate.flags]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 02 Nov 2000</p>
|
|
<p>
|
|
27.4.4.3, p4 says about the postcondition of the function: If
|
|
rdbuf()!=0 then state == rdstate(); otherwise
|
|
rdstate()==state|ios_base::badbit.
|
|
</p>
|
|
|
|
<p>
|
|
The expression on the right-hand-side of the operator==() needs to be
|
|
parenthesized in order for the whole expression to ever evaluate to
|
|
anything but non-zero.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Add parentheses like so: rdstate()==(state|ios_base::badbit).
|
|
</p>
|
|
<hr>
|
|
<a name="273"><h3>273. Missing ios_base qualification on members of a dependent class</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#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 02 Nov 2000</p>
|
|
<p>27.5.2.4.2, p4, and 27.8.1.6, p2, 27.8.1.7, p3, 27.8.1.9, p2,
|
|
27.8.1.10, p3 refer to in and/or out w/o ios_base:: qualification.
|
|
That's incorrect since the names are members of a dependent base
|
|
class (14.6.2 [temp.dep]) and thus not visible.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Qualify the names with the name of the class of which they are
|
|
members, i.e., ios_base.</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#Review">Review</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-volatile, non-reference type
|
|
</blockquote>
|
|
<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="275"><h3>275. Wrong type in num_get::get() overloads</h3></a><p>
|
|
<b>Section:</b> 22.2.2.1.1 <a href="lib-locales.html#lib.facet.num.get.members"> [lib.facet.num.get.members]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 02 Nov 2000</p>
|
|
<p>
|
|
In 22.2.2.1.1, we have a list of overloads for num_get<>::get().
|
|
There are eight overloads, all of which are identical except for the
|
|
last parameter. The overloads are:
|
|
</p>
|
|
<ul>
|
|
<li> long& </li>
|
|
<li> unsigned short& </li>
|
|
<li> unsigned int& </li>
|
|
<li> unsigned long& </li>
|
|
<li> short& </li>
|
|
<li> double& </li>
|
|
<li> long double& </li>
|
|
<li> void*& </li>
|
|
</ul>
|
|
|
|
<p>
|
|
There is a similar list, in 22.2.2.1.2, of overloads for
|
|
num_get<>::do_get(). In this list, the last parameter has
|
|
the types:
|
|
</p>
|
|
<ul>
|
|
<li> long& </li>
|
|
<li> unsigned short& </li>
|
|
<li> unsigned int& </li>
|
|
<li> unsigned long& </li>
|
|
<li> float& </li>
|
|
<li> double& </li>
|
|
<li> long double& </li>
|
|
<li> void*& </li>
|
|
</ul>
|
|
|
|
<p>
|
|
These two lists are not identical. They should be, since
|
|
<tt>get</tt> is supposed to call <tt>do_get</tt> with exactly
|
|
the arguments it was given.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>In 22.2.2.1.1 , change</p>
|
|
<pre>
|
|
iter_type get(iter_type in, iter_type end, ios_base& str,
|
|
ios_base::iostate& err, short& val) const;
|
|
</pre>
|
|
<p>to</p>
|
|
<pre>
|
|
iter_type get(iter_type in, iter_type end, ios_base& str,
|
|
ios_base::iostate& err, float& val) const;
|
|
</pre>
|
|
<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#Review">Review</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 , 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>
|
|
|
|
<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-active.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 ,
|
|
after paragraph 5:</p>
|
|
<blockquote>
|
|
<i>Invalidating</i> an iterator means modifying it such that
|
|
it may have a singular value. [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>
|
|
|
|
<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
|
|
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 .
|
|
</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="281"><h3>281. std::min() and max() requirements overly restrictive</h3></a><p>
|
|
<b>Section:</b> 25.3.7 <a href="lib-algorithms.html#lib.alg.min.max"> [lib.alg.min.max]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 02 Dec 2000</p>
|
|
<p>The requirements in 25.3.7, p1 and 4 call for T to satisfy the
|
|
requirements of <tt>LessThanComparable</tt> (20.1.2 )
|
|
and <tt>CopyConstructible</tt> (20.1.3 ).
|
|
Since the functions take and return their arguments and result by
|
|
const reference, I believe the <tt>CopyConstructible</tt> requirement
|
|
is unnecessary.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Remove the <tt>CopyConstructible</tt> requirement. Specifically, replace
|
|
25.3.7, p1 with</p>
|
|
<p>
|
|
<b>-1- Requires:</b> Type T is <tt>LessThanComparable</tt>
|
|
(20.1.2 ).
|
|
</p>
|
|
<p>and replace 25.3.7, p4 with</p>
|
|
<p>
|
|
<b>-4- Requires:</b> Type T is <tt>LessThanComparable</tt>
|
|
(20.1.2 ).
|
|
</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 .
|
|
</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 .
|
|
</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 doing.
|
|
]</i></p>
|
|
|
|
<hr>
|
|
<a name="283"><h3>283. std::replace() requirement incorrect/insufficient</h3></a><p>
|
|
<b>Section:</b> 25.2.4 <a href="lib-algorithms.html#lib.alg.replace"> [lib.alg.replace]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 15 Dec 2000</p>
|
|
<p>
|
|
The requirements in 25.2.4 , p1 that <tt>T</tt> to be
|
|
<tt>Assignable</tt> (23.1 ) 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 ) with respect to
|
|
one another.
|
|
</p>
|
|
|
|
<p>
|
|
Note that a similar problem occurs in several other places in section
|
|
25 as well (e.g., 25.1.6 , or 25.2.5 ) so
|
|
what really needs to happen is for all those places to be identified
|
|
and corrected. The proposed resolution below addresses only 25.2.4.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 25.2.4, p1 from</p>
|
|
|
|
<blockquote>
|
|
<b>-1- Requires:</b>Type <tt>T</tt> is <tt>Assignable</tt>
|
|
(23.1 ) (and, for <tt>replace()</tt>,
|
|
<tt>EqualityComparable</tt> (20.1.1 )).
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
<b>-1- Requires:</b>Type
|
|
<tt>std::iterator_traits<ForwardIterator>::value_type</tt>
|
|
is <tt>Assignable</tt> (23.1 ), the type <tt>T</tt> is
|
|
convertible to<tt>std::iterator_traits<ForwardIterator>::value_type</tt>,
|
|
(and, for <tt>replace()</tt>, types
|
|
<tt>std::iterator_traits<ForwardIterator>::value_type</tt> and
|
|
<tt>T</tt> are <tt>EqualityComparable</tt> (20.1.1 )
|
|
with respect to one another).
|
|
</blockquote>
|
|
|
|
<p><i>[
|
|
The LWG agrees with the general idea of the proposed resolution, but
|
|
not with the specific wording. (There is no definition in the
|
|
standard of what it means for one type to be EqualityComparable to
|
|
another.) Jeremy will provide new wording, and will review clause 25
|
|
for similar issues.
|
|
]</i></p>
|
|
|
|
<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 , 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 ], and since
|
|
function pointers with different the language linkage specifications
|
|
(7.5 ) are incompatible, whether this example is
|
|
well-formed is unspecified.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Replace the code snippet in the following text</p>
|
|
<blockquote>
|
|
<p>
|
|
<b>-6- </b>[<i>Example:</i>
|
|
</p>
|
|
<pre>
|
|
replace_if(v.begin(), v.end(), not1(bind2nd(ptr_fun(strcmp), "C")), "C++");
|
|
</pre>
|
|
</blockquote>
|
|
|
|
|
|
<p>with</p>
|
|
<blockquote>
|
|
<p>
|
|
<b>-6- </b>[<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>
|
|
</blockquote>
|
|
|
|
<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>
|
|
<hr>
|
|
<a name="285"><h3>285. minor editorial errors in fstream ctors</h3></a><p>
|
|
<b>Section:</b> 27.8.1.6 <a href="lib-iostreams.html#lib.ifstream.cons"> [lib.ifstream.cons]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 31 Dec 2000</p>
|
|
<p>27.8.1.6 , p2, 27.8.1.9 , p2, and
|
|
27.8.1.12 , p2 say about the effects of each constructor:
|
|
<a href="lib-iostreams.html#lib.ifstream.cons"> [lib.ifstream.cons]</a>
|
|
</p>
|
|
|
|
<p>... If that function returns a null pointer, calls
|
|
<tt>setstate(failbit)</tt> (which may throw <tt>ios_base::failure</tt>).
|
|
</p>
|
|
|
|
<p>The parenthetical note doesn't apply since the ctors cannot throw an
|
|
exception due to the requirement in 27.4.4.1 , p3
|
|
that <tt>exceptions()</tt> be initialized to <tt>ios_base::goodbit</tt>.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Strike the parenthetical note from the Effects clause in each of the
|
|
paragraphs mentioned above.
|
|
</p>
|
|
<hr>
|
|
<a name="286"><h3>286. <cstdlib> requirements missing size_t typedef</h3></a><p>
|
|
<b>Section:</b> 25.4 <a href="lib-algorithms.html#lib.alg.c.library"> [lib.alg.c.library]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Judy Ward <b>Date:</b> 30 Dec 2000</p>
|
|
<p>
|
|
The <cstdlib> header file contains prototypes for bsearch and
|
|
qsort (C++ Standard section 25.4 paragraphs 3 and 4) and other
|
|
prototypes (C++ Standard section 21.4 paragraph 1 table 49) that
|
|
require the typedef size_t. Yet size_t is not listed in the
|
|
<cstdlib> synopsis table 78 in section 25.4.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Add the type size_t to Table 78 (section 25.4) and add
|
|
the type size_t <cstdlib> to Table 97 (section C.2).
|
|
</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>Since size_t is in <stdlib.h>, it must also be in <cstdlib>.</p>
|
|
<hr>
|
|
<a name="288"><h3>288. <cerrno> requirements missing macro EILSEQ</h3></a><p>
|
|
<b>Section:</b> 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> Judy Ward <b>Date:</b> 30 Dec 2000</p>
|
|
<p>
|
|
ISO/IEC 9899:1990/Amendment1:1994 Section 4.3 States: "The list
|
|
of macros defined in <errno.h> is adjusted to include a new
|
|
macro, EILSEQ"
|
|
</p>
|
|
|
|
<p>
|
|
ISO/IEC 14882:1998(E) section 19.3 does not refer
|
|
to the above amendment.
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Update Table 26 (section 19.3) "Header <cerrno> synopsis"
|
|
and Table 95 (section C.2) "Standard Macros" to include EILSEQ.
|
|
</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-active.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="292"><h3>292. effects of a.copyfmt (a)</h3></a><p>
|
|
<b>Section:</b> 27.4.4.2 <a href="lib-iostreams.html#lib.basic.ios.members"> [lib.basic.ios.members]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 05 Jan 2001</p>
|
|
<p>The Effects clause of the member function <tt>copyfmt()</tt> in
|
|
27.4.4.2, p15 doesn't consider the case where the left-hand side
|
|
argument is identical to the argument on the right-hand side, that is
|
|
<tt>(this == &rhs)</tt>. If the two arguments are identical there
|
|
is no need to copy any of the data members or call any callbacks
|
|
registered with <tt>register_callback()</tt>. Also, as Howard Hinnant
|
|
points out in message c++std-lib-8149 it appears to be incorrect to
|
|
allow the object to fire <tt>erase_event</tt> followed by
|
|
<tt>copyfmt_event</tt> since the callback handling the latter event
|
|
may inadvertently attempt to access memory freed by the former.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change the Effects clause in 27.4.4.2, p15 from</p>
|
|
|
|
<blockquote>
|
|
<b>-15- Effects:</b>Assigns to the member objects of <tt>*this</tt>
|
|
the corresponding member objects of <tt>rhs</tt>, except that...
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
<b>-15- Effects:</b>If <tt>(this == &rhs)</tt> does nothing. Otherwise
|
|
assigns to the member objects of <tt>*this</tt> the corresponding member
|
|
objects of <tt>rhs</tt>, except that...
|
|
</blockquote>
|
|
<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 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 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 , 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 remain consistent. Nathan will provide new
|
|
wording.]</i></p>
|
|
|
|
<hr>
|
|
<a name="295"><h3>295. Is abs defined in <cmath>?</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#Ready">Ready</a> <b>Submitter:</b> Jens Maurer <b>Date:</b> 12 Jan 2001</p>
|
|
<p>
|
|
Table 80 lists the contents of the <cmath> header. It does not
|
|
list <tt>abs()</tt>. However, 26.5, paragraph 6, which lists added
|
|
signatures present in <cmath>, does say that several overloads
|
|
of <tt>abs()</tt> should be defined in <cmath>.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Add <tt>abs</tt> to Table 80. Also, remove the parenthetical list
|
|
of functions "(abs(), div(), rand(), srand())" from 26.5 ,
|
|
paragraph 1.
|
|
</p>
|
|
|
|
<p><i>[Copenhagen: Modified proposed resolution so that it also gets
|
|
rid of that vestigial list of functions in paragraph 1.]</i></p>
|
|
|
|
<hr>
|
|
<a name="296"><h3>296. Missing descriptions and requirements of pair operators</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#Review">Review</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 14 Jan 2001</p>
|
|
<p>The synopsis of the header <tt><utility></tt> in 20.2
|
|
lists the complete set of equality and relational operators for <tt>pair</tt>
|
|
but the section describing the template and the operators only describes
|
|
<tt>operator==()</tt> and <tt>operator<()</tt>, and it fails to mention
|
|
any requirements on the template arguments. The remaining operators are
|
|
not mentioned at all.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>Add the following after 20.2.2 , paragraph 5:</p>
|
|
|
|
<blockquote>
|
|
<blockquote>
|
|
<tt>template <class T1, class T2></tt>
|
|
<br><tt>bool operator!=(const pair<T1, T2>& x, const pair<T1,
|
|
T2>& y);</tt>
|
|
</blockquote>
|
|
|
|
<p>
|
|
<b>Requires: </b>Types <tt>T1</tt> and <tt>T2</tt> are
|
|
<tt>EqualityComparable</tt> (20.1.1 ).</p>
|
|
|
|
<p>
|
|
<b>Returns:</b> <tt>!(x == y)</tt>.</p>
|
|
</blockquote>
|
|
|
|
<p>Add the following after 20.2.2 , paragraph 6:</p>
|
|
|
|
<blockquote>
|
|
<blockquote>
|
|
<tt>template <class T1, class T2></tt>
|
|
<br><tt>bool operator>(const pair<T1, T2>& x, const pair<T1, T2>& y);</tt>
|
|
</blockquote>
|
|
|
|
<p>
|
|
<b>Requires: </b>Types <tt>T1</tt> and <tt>T2</tt> are
|
|
<tt>LessThanComparable</tt> (20.1.2 ).</p>
|
|
|
|
<p>
|
|
<b>Returns:</b> <tt>y < x</tt>.</p>
|
|
|
|
<blockquote>
|
|
<tt>template <class T1, class T2></tt>
|
|
<br><tt>bool operator<=(const pair<T1, T2>& x, const pair<T1, T2>& y);</tt>
|
|
</blockquote>
|
|
|
|
<p>
|
|
<b>Requires: </b>Types <tt>T1</tt> and <tt>T2</tt> are
|
|
<tt>LessThanComparable</tt> (20.1.2 ).</p>
|
|
|
|
<p>
|
|
<b>Returns: </b><tt>!(y < x)</tt>.</p>
|
|
|
|
<blockquote>
|
|
<tt>template <class T1, class T2></tt>
|
|
<br><tt>bool operator>=(const pair<T1, T2>& x, const pair<T1, T2>& y);</tt>
|
|
</blockquote>
|
|
|
|
<p>
|
|
<b>Requires: </b>Types <tt>T1</tt> and <tt>T2</tt> are
|
|
<tt>LessThanComparable</tt> (20.1.2 ).</p>
|
|
|
|
<p>
|
|
<b>Returns:</b> <tt>!(x < y)</tt>.</p>
|
|
</blockquote>
|
|
|
|
<p><i>[post-Copenhagen: modified proposed resolution so that it does
|
|
not create a new section 20.2.2.1. That would violate ISO rules: we
|
|
cannot have 20.2.2.1 unless we also have 20.2.2.2.]</i></p>
|
|
|
|
<hr>
|
|
<a name="297"><h3>297. const_mem_fun_t<>::argument_type should be const T*</h3></a><p>
|
|
<b>Section:</b> 20.3.8 <a href="lib-utilities.html#lib.member.pointer.adaptors"> [lib.member.pointer.adaptors]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 6 Jan 2001</p>
|
|
<p>The class templates <tt>const_mem_fun_t</tt> in 20.3.8, p8 and
|
|
<tt>const_mem_fun1_t</tt>
|
|
in 20.3.8, p9 derive from <tt>unary_function<T*, S></tt>, and
|
|
<tt>binary_function<T*,
|
|
A, S></tt>, respectively. Consequently, their <tt>argument_type</tt>, and
|
|
<tt>first_argument_type</tt>
|
|
members, respectively, are both defined to be <tt>T*</tt> (non-const).
|
|
However, their function call member operator takes a <tt>const T*</tt>
|
|
argument. It is my opinion that <tt>argument_type</tt> should be <tt>const
|
|
T*</tt> instead, so that one can easily refer to it in generic code. The
|
|
example below derived from existing code fails to compile due to the
|
|
discrepancy:
|
|
</p>
|
|
|
|
<p>
|
|
<tt>template <class T></tt>
|
|
<br><tt>void foo (typename T::argument_type arg) // #1</tt>
|
|
<br><tt>{</tt>
|
|
<br><tt> typename T::result_type (T::*pf) (typename
|
|
T::argument_type)
|
|
const = // #2</tt>
|
|
<br><tt> &T::operator();</tt>
|
|
<br><tt>}</tt>
|
|
</p>
|
|
|
|
<p><tt>struct X { /* ... */ };</tt></p>
|
|
|
|
<p>
|
|
<tt>int main ()</tt>
|
|
<br><tt>{</tt>
|
|
<br><tt> const X x;</tt>
|
|
<br><tt> foo<std::const_mem_fun_t<void, X>
|
|
>(&x);
|
|
// #3</tt>
|
|
<br><tt>}</tt>
|
|
</p>
|
|
|
|
<p>#1 <tt>foo()</tt> takes a plain unqualified <tt>X*</tt> as an argument
|
|
<br>#2 the type of the pointer is incompatible with the type of the member
|
|
function
|
|
<br>#3 the address of a constant being passed to a function taking a non-const
|
|
<tt>X*</tt>
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Replace the top portion of the definition of the class template
|
|
const_mem_fun_t in 20.3.8, p8
|
|
</p>
|
|
<p>
|
|
<tt>template <class S, class T> class const_mem_fun_t</tt>
|
|
<br><tt> : public
|
|
unary_function<T*, S> {</tt>
|
|
</p>
|
|
<p>with</p>
|
|
<p>
|
|
<tt>template <class S, class T> class const_mem_fun_t</tt>
|
|
<br><tt> : public
|
|
unary_function<<b>const</b> T*, S> {</tt>
|
|
</p>
|
|
<p>Also replace the top portion of the definition of the class template
|
|
const_mem_fun1_t in 20.3.8, p9</p>
|
|
<p>
|
|
<tt>template <class S, class T, class A> class const_mem_fun1_t</tt>
|
|
<br><tt> : public
|
|
binary_function<T*, A, S> {</tt>
|
|
</p>
|
|
<p>with</p>
|
|
<p>
|
|
<tt>template <class S, class T, class A> class const_mem_fun1_t</tt>
|
|
<br><tt> : public
|
|
binary_function<<b>const</b> T*, A, S> {</tt>
|
|
</p>
|
|
<p><b>Rationale:</b></p>
|
|
<p>This is simply a contradiction: the <tt>argument_type</tt> typedef,
|
|
and the argument type itself, are not the same.</p>
|
|
<hr>
|
|
<a name="298"><h3>298. ::operator delete[] requirement incorrect/insufficient</h3></a><p>
|
|
<b>Section:</b> 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> John A. Pedretti <b>Date:</b> 10 Jan 2001</p>
|
|
<p>
|
|
The default behavior of <tt>operator delete[]</tt> described in 18.4.1.2, p12 -
|
|
namely that for non-null value of <i>ptr</i>, the operator reclaims storage
|
|
allocated by the earlier call to the default <tt>operator new[]</tt> - is not
|
|
correct in all cases. Since the specified <tt>operator new[]</tt> default
|
|
behavior is to call <tt>operator new</tt> (18.4.1.2, p4, p8), which can be
|
|
replaced, along with <tt>operator delete</tt>, by the user, to implement their
|
|
own memory management, the specified default behavior of<tt> operator
|
|
delete[]</tt> must be to call <tt>operator delete</tt>.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 18.4.1.2, p12 from</p>
|
|
<blockquote>
|
|
<b>-12-</b> <b>Default behavior:</b>
|
|
<ul>
|
|
<li>
|
|
For a null value of <i><tt>ptr</tt></i> , does nothing.
|
|
</li>
|
|
<li>
|
|
Any other value of <i><tt>ptr</tt></i> shall be a value returned
|
|
earlier by a call to the default <tt>operator new[](std::size_t)</tt>.
|
|
[Footnote: The value must not have been invalidated by an intervening
|
|
call to <tt>operator delete[](void*)</tt> (17.4.3.7 ).
|
|
--- end footnote]
|
|
For such a non-null value of <i><tt>ptr</tt></i> , reclaims storage
|
|
allocated by the earlier call to the default <tt>operator new[]</tt>.
|
|
</li>
|
|
</ul>
|
|
</blockquote>
|
|
|
|
<p>to</p>
|
|
|
|
<blockquote>
|
|
<b>-12-</b> <b>Default behavior: </b>Calls <tt>operator
|
|
delete(</tt><i>ptr</i>)
|
|
or <tt>operator delete(<i>ptr</i>, std::nothrow)</tt> respectively.
|
|
</blockquote>
|
|
<p>and expunge paragraph 13.</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 ,
|
|
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 ,
|
|
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 , change the return type in table
|
|
75 from "convertible to T" to T&.</p>
|
|
|
|
<p>In section 24.1.5 , 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 , 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="301"><h3>301. basic_string template ctor effects clause omits allocator argument</h3></a><p>
|
|
<b>Section:</b> 21.3.1 <a href="lib-strings.html#lib.string.cons"> [lib.string.cons]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 27 Jan 2001</p>
|
|
<p>
|
|
The effects clause for the basic_string template ctor in 21.3.1, p15
|
|
leaves out the third argument of type Allocator. I believe this to be
|
|
a mistake.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Replace</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
<b>-15- Effects:</b> If <i><tt>InputIterator</tt></i> is an integral
|
|
type, equivalent to</p>
|
|
|
|
<blockquote><tt>basic_string(static_cast<size_type>(begin),
|
|
static_cast<value_type>(end))</tt></blockquote>
|
|
</blockquote>
|
|
|
|
<p>with</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
<b>-15- Effects:</b> If <i><tt>InputIterator</tt></i> is an integral
|
|
type, equivalent to</p>
|
|
|
|
<blockquote><tt>basic_string(static_cast<size_type>(begin),
|
|
static_cast<value_type>(end), <b>a</b>)</tt></blockquote>
|
|
</blockquote>
|
|
<hr>
|
|
<a name="303"><h3>303. Bitset input operator underspecified</h3></a><p>
|
|
<b>Section:</b> 23.3.5.3 <a href="lib-containers.html#lib.bitset.operators"> [lib.bitset.operators]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Matt Austern <b>Date:</b> 5 Feb 2001</p>
|
|
<p>
|
|
In 23.3.5.3, we are told that <tt>bitset</tt>'s input operator
|
|
"Extracts up to <i>N</i> (single-byte) characters from
|
|
<i>is</i>.", where <i>is</i> is a stream of type
|
|
<tt>basic_istream<charT, traits></tt>.
|
|
</p>
|
|
|
|
<p>
|
|
The standard does not say what it means to extract single byte
|
|
characters from a stream whose character type, <tt>charT</tt>, is in
|
|
general not a single-byte character type. Existing implementations
|
|
differ.
|
|
</p>
|
|
|
|
<p>
|
|
A reasonable solution will probably involve <tt>widen()</tt> and/or
|
|
<tt>narrow()</tt>, since they are the supplied mechanism for a single
|
|
character between <tt>char</tt> and arbitrary <tt>charT</tt>.
|
|
</p>
|
|
|
|
<p>Narrowing the input characters is not the same as widening the
|
|
literals <tt>'0'</tt> and <tt>'1'</tt>, because there may be some
|
|
locales in which more than one wide character maps to the narrow
|
|
character <tt>'0'</tt>. Narrowing means that alternate
|
|
representations may be used for bitset input, widening means that
|
|
they may not be.</p>
|
|
|
|
<p>Note that for numeric input, <tt>num_get<></tt>
|
|
(22.2.2.1.2/8) compares input characters to widened version of narrow
|
|
character literals.</p>
|
|
|
|
<p>From Pete Becker, in c++std-lib-8224:</p>
|
|
<blockquote>
|
|
<p>
|
|
Different writing systems can have different representations for the
|
|
digits that represent 0 and 1. For example, in the Unicode representation
|
|
of the Devanagari script (used in many of the Indic languages) the digit 0
|
|
is 0x0966, and the digit 1 is 0x0967. Calling narrow would translate those
|
|
into '0' and '1'. But Unicode also provides the ASCII values 0x0030 and
|
|
0x0031 for for the Latin representations of '0' and '1', as well as code
|
|
points for the same numeric values in several other scripts (Tamil has no
|
|
character for 0, but does have the digits 1-9), and any of these values
|
|
would also be narrowed to '0' and '1'.
|
|
</p>
|
|
|
|
<p>...</p>
|
|
|
|
<p>
|
|
It's fairly common to intermix both native and Latin
|
|
representations of numbers in a document. So I think the rule has to be
|
|
that if a wide character represents a digit whose value is 0 then the bit
|
|
should be cleared; if it represents a digit whose value is 1 then the bit
|
|
should be set; otherwise throw an exception. So in a Devanagari locale,
|
|
both 0x0966 and 0x0030 would clear the bit, and both 0x0967 and 0x0031
|
|
would set it. Widen can't do that. It would pick one of those two values,
|
|
and exclude the other one.
|
|
</p>
|
|
|
|
</blockquote>
|
|
|
|
<p>From Jens Maurer, in c++std-lib-8233:</p>
|
|
|
|
<blockquote>
|
|
<p>
|
|
Whatever we decide, I would find it most surprising if
|
|
bitset conversion worked differently from int conversion
|
|
with regard to alternate local representations of
|
|
numbers.
|
|
</p>
|
|
|
|
<p>Thus, I think the options are:</p>
|
|
<ul>
|
|
<li> Have a new defect issue for 22.2.2.1.2/8 so that it will
|
|
require the use of narrow().</li>
|
|
|
|
<li> Have a defect issue for bitset() which describes clearly
|
|
that widen() is to be used.</li>
|
|
</ul>
|
|
</blockquote>
|
|
<p><b>Proposed resolution:</b></p>
|
|
|
|
<p>Replace the first two sentences of paragraph 5 with:</p>
|
|
|
|
<blockquote>
|
|
Extracts up to <i>N</i> characters from <i>is</i>. Stores these
|
|
characters in a temporary object <i>str</i> of type
|
|
<tt>basic_string<charT, traits></tt>, then evaluates the
|
|
expression <tt><i>x</i> = bitset<N>(<i>str</i>)</tt>.
|
|
</blockquote>
|
|
|
|
<p>Replace the third bullet item in paragraph 5 with:</p>
|
|
<ul><li>
|
|
the next input character is neither <tt><i>is</i>.widen(0)</tt>
|
|
nor <tt><i>is</i>.widen(1)</tt> (in which case the input character
|
|
is not extracted).
|
|
</li></ul>
|
|
|
|
<p><b>Rationale:</b></p>
|
|
<p>Input for <tt>bitset</tt> should work the same way as numeric
|
|
input. Using <tt>widen</tt> does mean that alternative digit
|
|
representations will not be recognized, but this was a known
|
|
consequence of the design choice.</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/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>[Copenhagen: straw poll was 3-1 in favor, with many abstentions.
|
|
Nathan would like to see more guarantees than are in the proposed
|
|
resolution. He will discuss this issue with the other people who
|
|
care about it.]</i></p>
|
|
|
|
<hr>
|
|
<a name="306"><h3>306. offsetof macro and non-POD types</h3></a><p>
|
|
<b>Section:</b> 18.1 <a href="lib-support.html#lib.support.types"> [lib.support.types]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Steve Clamage <b>Date:</b> 21 Feb 2001</p>
|
|
<p>Spliced together from reflector messages c++std-lib-8294 and -8295:</p>
|
|
|
|
<p>18.1, paragraph 5, reads: "The macro <tt>offsetof</tt>
|
|
accepts a restricted set of <i>type</i> arguments in this
|
|
International Standard. <i>type</i> shall be a POD structure or a POD
|
|
union (clause 9). The result of applying the offsetof macro to a field
|
|
that is a static data member or a function member is
|
|
undefined."</p>
|
|
|
|
<p>For the POD requirement, it doesn't say "no diagnostic
|
|
required" or "undefined behavior". I read 1.4 , paragraph 1, to mean that a diagnostic is required.
|
|
It's not clear whether this requirement was intended. While it's
|
|
possible to provide such a diagnostic, the extra complication doesn't
|
|
seem to add any value.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Change 18.1, paragraph 5, to "If <i>type</i> is not a POD
|
|
structure or a POD union the results are undefined."</p>
|
|
|
|
<p><i>[Copenhagen: straw poll was 7-4 in favor. It was generally
|
|
agreed that requiring a diagnostic was inadvertent, but some LWG
|
|
members thought that diagnostics should be required whenever
|
|
possible.]</i></p>
|
|
|
|
<hr>
|
|
<a name="307"><h3>307. Lack of reference typedefs in container adaptors</h3></a><p>
|
|
<b>Section:</b> 23.2.3 <a href="lib-containers.html#lib.container.adaptors"> [lib.container.adaptors]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Howard Hinnant <b>Date:</b> 13 Mar 2001</p>
|
|
|
|
<p>From reflector message c++std-lib-8330. See also lib-8317.</p>
|
|
|
|
<p>
|
|
The standard is currently inconsistent in 23.2.3.2
|
|
paragraph 1 and 23.2.3.3 paragraph 1.
|
|
23.2.3.3/1, for example, says:
|
|
</p>
|
|
|
|
<blockquote>
|
|
-1- Any sequence supporting operations back(), push_back() and pop_back()
|
|
can be used to instantiate stack. In particular, vector (lib.vector), list
|
|
(lib.list) and deque (lib.deque) can be used.
|
|
</blockquote>
|
|
|
|
<p>But this is false: vector<bool> can not be used, because the
|
|
container adaptors return a T& rather than using the underlying
|
|
container's reference type.</p>
|
|
|
|
<p>This is a contradiction that can be fixed by:</p>
|
|
|
|
<ol>
|
|
<li>Modifying these paragraphs to say that vector<bool>
|
|
is an exception.</li>
|
|
<li>Removing the vector<bool> specialization.</li>
|
|
<li>Changing the return types of stack and priority_queue to use
|
|
reference typedef's.</li>
|
|
</ol>
|
|
|
|
<p>
|
|
I propose 3. This does not preclude option 2 if we choose to do it
|
|
later (see issue <a href="lwg-active.html#96">96</a>); the issues are independent. Option
|
|
3 offers a small step towards support for proxied containers. This
|
|
small step fixes a current contradiction, is easy for vendors to
|
|
implement, is already implemented in at least one popular lib, and
|
|
does not break any code.
|
|
</p>
|
|
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Summary: Add reference and const_reference typedefs to queue,
|
|
priority_queue and stack. Change return types of "value_type&" to
|
|
"reference". Change return types of "const value_type&" to
|
|
"const_reference". Details:</p>
|
|
|
|
<p>Change 23.2.3.1/1 from:</p>
|
|
|
|
<pre>
|
|
namespace std {
|
|
template <class T, class Container = deque<T> >
|
|
class queue {
|
|
public:
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::size_type size_type;
|
|
typedef Container container_type;
|
|
protected:
|
|
Container c;
|
|
|
|
public:
|
|
explicit queue(const Container& = Container());
|
|
|
|
bool empty() const { return c.empty(); }
|
|
size_type size() const { return c.size(); }
|
|
value_type& front() { return c.front(); }
|
|
const value_type& front() const { return c.front(); }
|
|
value_type& back() { return c.back(); }
|
|
const value_type& back() const { return c.back(); }
|
|
void push(const value_type& x) { c.push_back(x); }
|
|
void pop() { c.pop_front(); }
|
|
};
|
|
</pre>
|
|
|
|
<p>to:</p>
|
|
|
|
<pre>
|
|
namespace std {
|
|
template <class T, class Container = deque<T> >
|
|
class queue {
|
|
public:
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::reference reference;
|
|
typedef typename Container::const_reference const_reference;
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::size_type size_type;
|
|
typedef Container container_type;
|
|
protected:
|
|
Container c;
|
|
|
|
public:
|
|
explicit queue(const Container& = Container());
|
|
|
|
bool empty() const { return c.empty(); }
|
|
size_type size() const { return c.size(); }
|
|
reference front() { return c.front(); }
|
|
const_reference front() const { return c.front(); }
|
|
reference back() { return c.back(); }
|
|
const_reference back() const { return c.back(); }
|
|
void push(const value_type& x) { c.push_back(x); }
|
|
void pop() { c.pop_front(); }
|
|
};
|
|
</pre>
|
|
|
|
<p>Change 23.2.3.2/1 from:</p>
|
|
|
|
<pre>
|
|
namespace std {
|
|
template <class T, class Container = vector<T>,
|
|
class Compare = less<typename Container::value_type> >
|
|
class priority_queue {
|
|
public:
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::size_type size_type;
|
|
typedef Container container_type;
|
|
protected:
|
|
Container c;
|
|
Compare comp;
|
|
|
|
public:
|
|
explicit priority_queue(const Compare& x = Compare(),
|
|
const Container& = Container());
|
|
template <class InputIterator>
|
|
priority_queue(InputIterator first, InputIterator last,
|
|
const Compare& x = Compare(),
|
|
const Container& = Container());
|
|
|
|
bool empty() const { return c.empty(); }
|
|
size_type size() const { return c.size(); }
|
|
const value_type& top() const { return c.front(); }
|
|
void push(const value_type& x);
|
|
void pop();
|
|
};
|
|
// no equality is provided
|
|
}
|
|
</pre>
|
|
|
|
<p>to:</p>
|
|
|
|
<pre>
|
|
namespace std {
|
|
template <class T, class Container = vector<T>,
|
|
class Compare = less<typename Container::value_type> >
|
|
class priority_queue {
|
|
public:
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::reference reference;
|
|
typedef typename Container::const_reference const_reference;
|
|
typedef typename Container::size_type size_type;
|
|
typedef Container container_type;
|
|
protected:
|
|
Container c;
|
|
Compare comp;
|
|
|
|
public:
|
|
explicit priority_queue(const Compare& x = Compare(),
|
|
const Container& = Container());
|
|
template <class InputIterator>
|
|
priority_queue(InputIterator first, InputIterator last,
|
|
const Compare& x = Compare(),
|
|
const Container& = Container());
|
|
|
|
bool empty() const { return c.empty(); }
|
|
size_type size() const { return c.size(); }
|
|
const_reference top() const { return c.front(); }
|
|
void push(const value_type& x);
|
|
void pop();
|
|
};
|
|
// no equality is provided
|
|
}
|
|
</pre>
|
|
|
|
<p>And change 23.2.3.3/1 from:</p>
|
|
|
|
<pre>
|
|
namespace std {
|
|
template <class T, class Container = deque<T> >
|
|
class stack {
|
|
public:
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::size_type size_type;
|
|
typedef Container container_type;
|
|
protected:
|
|
Container c;
|
|
|
|
public:
|
|
explicit stack(const Container& = Container());
|
|
|
|
bool empty() const { return c.empty(); }
|
|
size_type size() const { return c.size(); }
|
|
value_type& top() { return c.back(); }
|
|
const value_type& top() const { return c.back(); }
|
|
void push(const value_type& x) { c.push_back(x); }
|
|
void pop() { c.pop_back(); }
|
|
};
|
|
|
|
template <class T, class Container>
|
|
bool operator==(const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator< (const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator!=(const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator> (const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator>=(const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator<=(const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
}
|
|
</pre>
|
|
|
|
<p>to:</p>
|
|
|
|
<pre>
|
|
namespace std {
|
|
template <class T, class Container = deque<T> >
|
|
class stack {
|
|
public:
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::reference reference;
|
|
typedef typename Container::const_reference const_reference;
|
|
typedef typename Container::size_type size_type;
|
|
typedef Container container_type;
|
|
protected:
|
|
Container c;
|
|
|
|
public:
|
|
explicit stack(const Container& = Container());
|
|
|
|
bool empty() const { return c.empty(); }
|
|
size_type size() const { return c.size(); }
|
|
reference top() { return c.back(); }
|
|
const_reference top() const { return c.back(); }
|
|
void push(const value_type& x) { c.push_back(x); }
|
|
void pop() { c.pop_back(); }
|
|
};
|
|
|
|
template <class T, class Container>
|
|
bool operator==(const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator< (const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator!=(const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator> (const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator>=(const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
template <class T, class Container>
|
|
bool operator<=(const stack<T, Container>& x,
|
|
const stack<T, Container>& y);
|
|
}
|
|
</pre>
|
|
|
|
<p><i>[Copenhagen: This change was discussed before the IS was released
|
|
and it was deliberately not adopted. Nevertheless, the LWG believes
|
|
(straw poll: 10-2) that it is a genuine defect.]</i></p>
|
|
|
|
<hr>
|
|
<a name="308"><h3>308. Table 82 mentions unrelated headers</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#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 15 Mar 2001</p>
|
|
<p>
|
|
Table 82 in section 27 mentions the header <cstdlib> for String
|
|
streams (27.7 ) and the headers <cstdio> and
|
|
<cwchar> for File streams (27.8 ). It's not clear
|
|
why these headers are mentioned in this context since they do not
|
|
define any of the library entities described by the
|
|
subclauses. According to 17.4.1.1 , only such headers
|
|
are to be listed in the summary.
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Remove <cstdlib> and <cwchar> from
|
|
Table 82.</p>
|
|
|
|
<p><i>[Copenhagen: changed the proposed resolution slightly. The
|
|
original proposed resolution also said to remove <cstdio> from
|
|
Table 82. However, <cstdio> is mentioned several times within
|
|
section 27.8 , including 27.8.2 .]</i></p>
|
|
|
|
<hr>
|
|
<a name="309"><h3>309. Does sentry catch exceptions?</h3></a><p>
|
|
<b>Section:</b> 27.6 <a href="lib-iostreams.html#lib.iostream.format"> [lib.iostream.format]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 19 Mar 2001</p>
|
|
<p>
|
|
The descriptions of the constructors of basic_istream<>::sentry
|
|
(27.6.1.1.2 ) and basic_ostream<>::sentry
|
|
(27.6.2.3 ) 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 , 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 , 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 , 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 , 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 , 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 , 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#Review">Review</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>
|
|
<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#Review">Review</a> <b>Submitter:</b> Andy Sawyer <b>Date:</b> 21 Mar 2001</p>
|
|
|
|
<p>In 27.6.2.1 , 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 , remove the
|
|
<i>// partial specializationss</i> comment.</p>
|
|
<hr>
|
|
<a name="312"><h3>312. Table 27 is missing headers</h3></a><p>
|
|
<b>Section:</b> 20 <a href="lib-utilities.html#lib.utilities"> [lib.utilities]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Ready</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 29 Mar 2001</p>
|
|
<p>Table 27 in section 20 lists the header <memory> (only) for
|
|
Memory (lib.memory) but neglects to mention the headers
|
|
<cstdlib> and <cstring> that are discussed in 20.4.6 .</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>Add <cstdlib> and <cstring> to Table 27, in the same row
|
|
as <memory>.</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#New">New</a> <b>Submitter:</b> Andy Sawyer <b>Date:</b> 1 May 2001</p>
|
|
<p>
|
|
23.2.2.4 , 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). Change the
|
|
complexity from "(last - first) -1 applications of the corresponding
|
|
predicate" to "distance(first,last)-1 applications of the corresponding
|
|
predicate.
|
|
</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#New">New</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#New">New</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 support those specializations...
|
|
</blockquote>
|
|
<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#New">New</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-active.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#New">New</a> <b>Submitter:</b> Beman Dawes <b>Date:</b> 15 May 2001</p>
|
|
<p>The standard specifies 17.3.1.3 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 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 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 be null or the value returned by an
|
|
earlier call ...</p>
|
|
</blockquote>
|
|
|
|
<p>In 18.4.1.2 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 be 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#New">New</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>
|
|
<p>PostCondition: *this == list<T, Allocator>(first, last)</p>
|
|
<p>Notes: If an exception is thrown, the contents of the list are
|
|
indeterminate.</p>
|
|
</blockquote>
|
|
|
|
<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>
|
|
<p>PostCondition: *this == list<T, Allocator>(n, t)</p>
|
|
<p>Notes: If an exception is thrown, the contents of the list are self
|
|
consistent but indeterminate.</p>
|
|
</blockquote>
|
|
<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#New">New</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>
|
|
<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#New">New</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#New">New</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><b>Proposed resolution:</b></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#New">New</a> <b>Submitter:</b> Dave Abrahams <b>Date:</b> 7 June 2001</p>
|
|
|
|
<p>Table 73 suggests that output iterators have value types. It says
|
|
defines 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 "*i'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>A sketch of one proposed resolution, without language: Make it
|
|
clear that the notion of "value type" does not apply to output
|
|
iterators.</p>
|
|
|
|
<blockquote>
|
|
Put an "except for output iterators" qualification in 24.1/1; remove
|
|
the note in table 73 about "a = t" and "X(a) = t"; put language in
|
|
24.1.2 paragraph 1 saying that "t" is a value of whatever type or
|
|
types for which "*i = t" is defined and that an output iterator need
|
|
not have a unique value type; change 24.3.1/1 to say that an output
|
|
iterator may, but need not, define
|
|
iterator_traits<Iterator>::difference_type
|
|
iterator_traits<Iterator>::value_type as void.
|
|
</blockquote>
|
|
|
|
<p>A sketch of an alternate proposed resolution, also without
|
|
language: Require every output iterator to have a value type, just
|
|
like other kinds of iterators.</p>
|
|
|
|
<blockquote>
|
|
Put an "except for output iterators" qualification in 24.1/1; remove
|
|
the note in table 73 about "a = t" and "X(a) = t"; put language in
|
|
24.1.2 paragraph 1 saying that an output iterator's value type is the
|
|
type for which "*i = t" is defined; remove the note in 24.3.1/1 saying
|
|
that iterator_traits<>::value_type is void for an output
|
|
iterator; change all of the predefined output iterators
|
|
(ostream_iterator, ostreambuf_iterator, back_insert_iterator,
|
|
front_insert_iterator, insert_iterator) so that they have non-void
|
|
value types.
|
|
</blockquote>
|
|
|
|
<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#New">New</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>
|
|
The moneypunct facet (or its derivative) installed in named locales
|
|
other than "C" will most commonly return the value "\003" (not "3").
|
|
</blockquote>
|
|
<p><b>Rationale:</b></p>
|
|
<p>
|
|
Note that the proposed resolution is sufficiently vague to allow
|
|
implementations to implement the behavior of both moneypunct and
|
|
moneypunct_byname to be implemented by the base. This may or may
|
|
not be desirable depending on whether we want the base behavior
|
|
to strictly reflect the "C" locale (only) and the derived behavior
|
|
to implement the behavior specific to the named locales. This
|
|
distinction would be detectable by obtaining a reference to
|
|
moneypunct_byname, say mp, and calling mp.do_grouping() or
|
|
mp.moneypunct<charT>::do_grouping() to get one or the other.
|
|
</p>
|
|
<hr>
|
|
<a name="326"><h3>326. Missing typedef in moneypunct_byname</h3></a><p>
|
|
<b>Section:</b> 22.2.6.4 <a href="lib-locales.html#lib.locale.moneypunct.byname"> [lib.locale.moneypunct.byname]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 05 Jul 2001</p>
|
|
<p>The definition of the moneypunct facet contains the typedefs char_type
|
|
and string_type. Only one of these names, string_type, is defined in
|
|
the derived facet, moneypunct_byname.</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>For consistency with the numpunct facet, add a typedef for
|
|
char_type to the definition of the moneypunct_byname facet in
|
|
22.2.6.4 .</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#New">New</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 , change</p>
|
|
<pre>
|
|
time_get<wchar_t, OutputIterator>
|
|
time_get_byname<wchart, OutputIterator>
|
|
</pre>
|
|
<p>to</p>
|
|
<pre>
|
|
time_get<wchar_t, InputIterator>
|
|
time_get_byname<wchart, InputIterator>
|
|
</pre>
|
|
<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#New">New</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>
|
|
<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#New">New</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 and
|
|
section 23.2.4.3 .
|
|
</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.5p5 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() after the most
|
|
recent call to reserve().
|
|
</blockquote>
|
|
|
|
<hr>
|
|
<a name="330"><h3>330. Misleading "exposition only" value in class locale definition</h3></a><p>
|
|
<b>Section:</b> 22.1.1 <a href="lib-locales.html#lib.locale"> [lib.locale]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> Martin Sebor <b>Date:</b> 15 Jul 2001</p>
|
|
<p>
|
|
The "exposition only" value of the std::locale::none constant shown in
|
|
the definition of class locale is misleading in that it on many
|
|
systems conflicts with the value assigned to one if the LC_XXX
|
|
constants (specifically, LC_COLLATE on AIX, LC_ALL on HP-UX, LC_CTYPE
|
|
on Linux and SunOS). This causes incorrect behavior when such a
|
|
constant is passed to one of the locale member functions that accept a
|
|
locale::category argument and interpret it as either the C LC_XXX
|
|
constant or a bitmap of locale::category values. At least three major
|
|
implementations adopt the suggested value without a change and
|
|
consequently suffer from this problem.
|
|
</p>
|
|
|
|
<p>
|
|
For instance, the following code will (presumably) incorrectly copy facets
|
|
belonging to the collate category from the German locale on AIX:
|
|
</p>
|
|
|
|
<pre>
|
|
std::locale l (std::locale ("C"), "de_DE", std::locale::none);
|
|
</pre>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Change the value from 0 to some other bit value, say 0x400, distinct
|
|
from any of the other values shown.
|
|
</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#New">New</a> <b>Submitter:</b> PremAnand M. Rao <b>Date:</b> 23 Aug 2001</p>
|
|
<p>
|
|
With the change in 17.4.4.8 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 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>Two alternatives:</p>
|
|
<ol>
|
|
<li>Change the declaration of ~failure() to virtual ~failure() throw();</li>
|
|
<li>Remove the declaration of ~failure().</li>
|
|
</ol>
|
|
<hr>
|
|
<a name="332"><h3>332. Consider adding increment and decrement operators to std::fpos< T > </h3></a><p>
|
|
<b>Section:</b> 27.4.3 <a href="lib-iostreams.html#lib.fpos"> [lib.fpos]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a> <b>Submitter:</b> PremAnand M. Rao <b>Date:</b> 27 Aug 2001</p>
|
|
<p>
|
|
Increment and decrement operators are missing from
|
|
Table 88 -- Position type requirements in 27.4.3 .
|
|
</p>
|
|
<p><b>Proposed resolution:</b></p>
|
|
<p>
|
|
Table 88 (section 27.4.3) -- Position type requirements
|
|
be updated to include increment and decrement operators.
|
|
</p>
|
|
|
|
<pre>
|
|
expression return type operational note
|
|
|
|
++p fpos& p += O(1)
|
|
p++ fpos { P tmp = p;
|
|
++p;
|
|
return tmp; }
|
|
--p fpos& p -= O(1)
|
|
p-- fpos { P tmp = p;
|
|
--p;
|
|
return tmp; }
|
|
</pre>
|
|
|
|
<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#New">New</a> <b>Submitter:</b> PremAnand M. Rao <b>Date:</b> 27 Aug 2001</p>
|
|
<p>A footnote in 27.6.2.7 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>
|
|
<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#New">New</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><b>Proposed resolution:</b></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>
|
|
Note that this is a "relaxing" of requirment and won't
|
|
make any currently conforming implementation on this
|
|
point to become non-conforming because of the change.
|
|
</p>
|
|
|
|
<p>
|
|
There is a small risk that current code may be depending
|
|
on the number of temporaries created by map::operator[];
|
|
but I think that such dependencies would be present only
|
|
in code that is most probably already non portable as
|
|
the number of copies of parameters isn't guaranteed by
|
|
the standard (in the current wording there's just an
|
|
implicit *minimum* number of required copies).
|
|
</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#New">New</a> <b>Submitter:</b> Andy Sawyer <b>Date:</b> 06 Sep 2001</p>
|
|
<p>
|
|
Table 37, in 21.1.1 , 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 a reference to CharT
|
|
</blockquote>
|
|
|
|
<p>and change the description of assign in the table to:</p>
|
|
<pre>
|
|
X::assign(r,d) assigns r = d
|
|
</pre>
|
|
<p>----- End of document -----</p>
|
|
</body>
|
|
</html>
|