From 7d31a1f43716b73d356552e8879d061f8f5a3dbc Mon Sep 17 00:00:00 2001
From: Paolo Carlini Reference ISO/IEC IS 14882:1998(E) Also see:open
clear the error flags.
-
Doc. no.
-N1762=05-0022
+N1830=05-0090
Date:
-2005-03-04
+2005-06-24
Project:
@@ -17,10 +17,10 @@
Reply to:
-Matt Austern <austern@google.com>
+Howard Hinnant <howard.hinnant@gmail.com>
C++ Standard Library Active Issues List (Revision 35)
+C++ Standard Library Active Issues List (Revision R37)
@@ -88,19 +88,28 @@
directory as the issues list files.
Straw poll: (1) 5; (2) 0; (3) 8.
-Further discussion from Santa Cruz:
- -There was some discussion of what the intent of our error - reporting mechanism was. There was general agreement on the - following principles:
-The crux of the disagreement was that some people, but not all, - believed that the design was also based on a fourth principle: - whenever converstion fails and failbit is set, nothing is to be - extracted and the value of the variable being extracted into is - guaranteed to be unchanged.
- -Some people believe that upon overflow, an implementation should - "extract" a special value that allows the user to tell that it was - overflow instead of some other kind of error. Straw poll: 1 person - believed the standard should require that, 2 thought it should - forbid it, and 6 thought the standard should allow but not require - it.
Proposed resolution:
-typo: 22.2.2.2.2 [lib.facet.num.put.virtuals], para 2, bullet 3. Strike "in." from -the end.
- -Change 22.2.2.2 [lib.locale.nm.put], para 11, bullet 2 from:
--The sequence of chars accumulated in stage 2 would have -caused scanf to report an input failure. ios_base::failbit is -assigned to err. -- -
to:
--The sequence of chars accumulated in stage 2 would have -caused scanf to report an input failure or to store a value -outside the range representable by val. ios_base::failbit is -assigned to err. --
[PJP provided wording. this treats overflow or underflow the same -as an ill-formed field. It's not exactly the consensus from Santa -Cruz, but he thinks it's the simplest and most robust rule and that it -corresponds to widespread common practice.]
- -[Kona: Wording here still isn't quite right, partly because it -refers to scanf and the scanf description of error conditions is -murky. The LWG had to do a very close reading of scanf in an attempt -to figure out what this proposed resolution means. General agreement -that the correct solution: (1) should not refer to scanf behavior, (2) -should not set errno, (3) should allow users who care to figure out -what kind of error happened. Martin will provide wording, Howard may -help.]
+Discussed at Lillehammer. General outline of what we want the + solution to look like: we want to say that overflow is an error, and + provide a way to distinguish overflow from other kinds of errors. + Choose candidate field the same way scanf does, but don't describe + the rest of the process in terms of format. If a finite input field + is too large (positive or negative) to be represented as a finite + value, then set failbit and assign the nearest representable value. + Bill will provide wording.
Section: 23.2.5 [lib.vector.bool] Status: Open Submitter: AFNOR Date: 7 Oct 1998
@@ -591,147 +544,18 @@ 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.] -[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.]
- -[Redmond: briefly discussed, since there are options for C++0x - that weren't reasonable for TC1. Two options were discussed. (1) - deprecate std::vector<bool> and introduce std::bit_vector. Then - gradually, over a period of years, we could reintroduce - std::vector<bool> but this time as an ordinary vector. (2) Change - iterarator and container requirements so that vector<bool> will - be a fully conforming container. These options are not mutually - exclusive.]
-Section: 23.1.2 [lib.associative.reqmts], 23.1.1 [lib.sequence.reqmts] Status: Ready Submitter: Andrew Koenig Date: 2 Mar 1999
-Table 67 (23.1.1) says that container::erase(iterator) returns an -iterator. Table 69 (23.1.2) says that in addition to this requirement, -associative containers also say that container::erase(iterator) -returns void. That's not an addition; it's a change to the -requirements, which has the effect of making associative containers -fail to meet the requirements for containers.
-Proposed resolution:
- --In 23.1.2 [lib.associative.reqmts], in Table 69 Associative container -requirements, change the return type of a.erase(q) from -void to iterator. Change the -assertion/not/pre/post-condition from "erases the element pointed to -by q" to "erases the element pointed to by q. -Returns an iterator pointing to the element immediately following q -prior to the element being erased. If no such element exists, a.end() -is returned." -
- --In 23.1.2 [lib.associative.reqmts], in Table 69 Associative container -requirements, change the return type of a.erase(q1, q2) -from void to iterator. Change the -assertion/not/pre/post-condition from "erases the elements in the -range [q1, q2)" to "erases the elements in the range [q1, -q2). Returns q2." -
- --In 23.3.1 [lib.map], in the map class synopsis; and -in 23.3.2 [lib.multimap], in the multimap class synopsis; and -in 23.3.3 [lib.set], in the set class synopsis; and -in 23.3.4 [lib.multiset], in the multiset class synopsis: -change the signature of the first erase overload to -
-iterator erase(iterator position); --
and change the signature of the third erase overload to
-iterator erase(iterator first, iterator last); -- - -
[Pre-Kona: reopened at the request of Howard Hinnant]
- -[Post-Kona: the LWG agrees the return type should be -iterator, not void. (Alex Stepanov agrees too.) -Matt provided wording.]
- -[ - Sydney: the proposed wording went in the right direction, but it - wasn't good enough. We want to return an iterator from the range form - of erase as well as the single-iterator form. Also, the wording is - slightly different from the wording we have for sequences; there's no - good reason for having a difference. Matt provided new wording, - which we will review at the next meeting. -]
- -Section: 20.1.5 [lib.allocator.requirements], 23.1 [lib.container.requirements] Status: Open Submitter: Andy Sawyer Date: 21 Oct 1999
-Must the value returned by max_size() be unchanged from call to call?
- -Must the value returned from max_size() be meaningful?
- -Possible meanings identified in lib-6827:
- -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.
-
-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.
-
-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.
-
-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.
Proposed resolution:
-Change 20.1.5 [lib.allocator.requirements] table 32 max_size() wording from:
-
- the largest value that can meaningfully be
-passed to X::allocate
-to:
- the value of the largest constant expression
-(5.19 [expr.const]) that could ever meaningfully be passed to X::allocate
-Change 23.1 [lib.container.requirements] table 65 max_size() wording from:
-
- size() of the largest possible container.
-to:
- the value of the largest constant expression
-(5.19 [expr.const]) that could ever meaningfully be returned by X::size().
-
Discussed at Lillehammer. General agreement that we should + deprecate vector<bool> and introduce this functionality under + a different name, e.g. bit_vector. This might make it possible to + remove the vector<bool> specialization in the standard that comes + after C++0x. There was also a suggestion that + in C++0x we could additional say that it's implementation defined + whether vector<bool> refers to the specialization or to the + primary template, but there wasn't general agreement that this was a + good idea.
-[Kona: The LWG informally discussed this and asked Andy Sawyer to submit -an issue.]
+We need a paper for the new bit_vector class.
-[Tokyo: The LWG believes (1) above is the intended meaning.]
- -[Post-Tokyo: Beman Dawes supplied the above resolution at the -request of the LWG. 21.3.3 [lib.string.capacity] 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).]
- -[Copenhagen: Exactly what max_size 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.]
Section: 18.2.1 [lib.limits] Status: Open Submitter: Stephen Cleary Date: 21 Dec 1999
@@ -742,91 +566,10 @@ pointers are scalar types, neither of which should have specializations of numeric_limits.
Proposed resolution:
-Change 18.2 [lib.support.limits] para 1 from:
-- -- -The headers <limits>, <climits>, and <cfloat> -supply characteristics of implementation-dependent fundamental types -(3.9.1).
-
to:
-- -- -The headers <limits>, <climits>, and <cfloat> -supply characteristics of implementation-dependent arithmetic types -(3.9.1).
-
Change 18.2.1 [lib.limits] para 1 from:
-- -- -The numeric_limits component provides a C++ program with -information about various properties of the implementation's -representation of the fundamental -types.
-
to:
-- -- -The numeric_limits component provides a C++ program with -information about various properties of the implementation's -representation of the arithmetic -types.
-
Change 18.2.1 [lib.limits] para 2 from:
-- -- -Specializations shall be provided for each fundamental type. . .
-
to:
-- -- -Specializations shall be provided for each arithmetic type. . .
-
Change 18.2.1 [lib.limits] para 4 from:
-- -- -Non-fundamental standard types. . .
-
to:
-- -- -Non-arithmetic standard types. . .
-
Change 18.2.1.1 [lib.numeric.limits] para 1 from:
-- -- -The member is_specialized makes it possible to distinguish between -fundamental types, which have specializations, and non-scalar types, -which -do not.
-
to:
-- -- -The member is_specialized makes it possible to distinguish between -arithmetic types, which have specializations, and non-arithmetic types, -which do not.
-
[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.]
+[Lillehammer: it remains true that numeric_limits is using + imprecise language. However, none of the proposals for changed + wording are clearer. A redesign of numeric_limits is needed, but this + is more a task than an open issue.]
Section: 23.1.2 [lib.associative.reqmts] Status: Open Submitter: Andrew Koenig Date: 30 Apr 2000
@@ -923,8 +666,20 @@ enough to make the detailed semantics hard to satisfy."]
[Curaçao: Nathan should give us the alternative wording he suggests so the LWG can decide between the two options.]
+[Lillehammer: The LWG previously rejected the more detailed + semantics, because it seemed more loike a new feature than like + defect fixing. We're now more sympathetic to it, but we (especially + Bill) are still worried about performance. N1780 describes a naive + algorithm, but it's not clear whether there is a non-naive + implementation. Is it possible to implement this as efficently as + the current version of insert?]
+ +[Post Lillehammer: N1780 updated in post meeting mailing with +feedback from Lillehammer with more information regarding performance. +]
+Section: 23.2.4.3 [lib.vector.modifiers] Status: Open Submitter: Lisa Lippincott Date: 06 June 2000
+Section: 23.2.4.3 [lib.vector.modifiers] Status: Review Submitter: Lisa Lippincott Date: 06 June 2000
Paragraph 2 of 23.2.4.3 [lib.vector.modifiers] describes the complexity of vector::insert:
@@ -944,17 +699,6 @@ of vector::insert: it requires that an arbitrary number of elements can be added at the end of a vector in constant time. -At the risk of strengthening the requirement, I suggest simply
- -- Complexity: The complexity is linear in the number of elements - inserted plus the distance to the end of the vector. -- -
For input iterators, one may achieve this complexity by first -inserting at the end of the vector, and then using -rotate.
-I looked to see if deque had a similar problem, and was surprised to find that deque places no requirement on the complexity of inserting multiple elements (23.2.1.3 [lib.deque.modifiers], @@ -969,8 +713,19 @@ paragraph 3):
takes constant time and causes a single call to the copy constructor of T. +Proposed resolution:
+ +Change Paragraph 2 of 23.2.4.3 [lib.vector.modifiers] to
++ Complexity: The complexity is linear in the number of elements + inserted plus the distance to the end of the vector. ++ +
[For input iterators, one may achieve this complexity by first + inserting at the end of the vector, and then using + rotate.]
-I suggest:
+Change 23.2.1.3 [lib.deque.modifiers], paragraph 3, to:
Complexity: The complexity is linear in the number of elements @@ -979,19 +734,13 @@ paragraph 3): beginning or the end of a deque causes a single call to the copy constructor of T.-
Proposed resolution:
-[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 c1 * N -+ c2 * distance(i, end()). 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.]
+Rationale:
+This is a real defect, and proposed resolution fixes it: some + complexities aren't specified that should be. This proposed + resolution does constrain deque implementations (it rules out the + most naive possible implementations), but the LWG doesn't see a + reason to permit that implementation.
Section: 19.1 [lib.std.exceptions] Status: Open Submitter: Dave Abrahams Date: 01 Aug 2000
@@ -1137,7 +886,7 @@ intended here is that the copy constructors can't fail.Section: 20.1.5 [lib.allocator.requirements] Status: Open Submitter: Matt Austern Date: 22 Aug 2000
-From lib-7752: +>From lib-7752:
@@ -1204,7 +953,7 @@ 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.]
Section: 24.4.1 [lib.reverse.iterators] Status: Open Submitter: Steve Cleary Date: 27 Nov 2000
+Section: 24.4.1 [lib.reverse.iterators] Status: Ready Submitter: Steve Cleary Date: 27 Nov 2000
This came from an email from Steve Cleary to Fergus in reference to issue 179. The library working group briefly discussed @@ -1265,6 +1014,11 @@ make this change without implementation experience. It may be desirable to provide this feature in a different way. ]
+[ +Lillehammer: We now have implementation experience, and agree that +this solution is safe and correct. +]
+Section: 25.1.1 [lib.alg.foreach] Status: Open Submitter: Angelika Langer Date: 03 Jan 2001
The specification of the for_each algorithm does not have a @@ -1292,25 +1046,14 @@ understand that there are restrictions even if the description of the algorithm does not say so.
Proposed resolution:
-Add a "Requires" section to section 25.1.1 similar to those -proposed for transform and the numeric algorithms (see issue -242): -
- -- -2- Requires: In the range [first, last], f shall not invalidate - iterators or subranges. -- -
[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 -for_each. -]
+[Lillehammer: This is more general than for_each. We don't want + the function object in transform invalidiating iterators + either. There should be a note somewhere in clause 17 (17, not 25) + saying that user code operating on a range may not invalidate + iterators unless otherwise specified. Bill will provide wording.]
Section: 17.4.3.1.1 [lib.macro.names] Status: Open Submitter: James Kanze Date: 11 Jan 2001
+Section: 17.4.3.1.1 [lib.macro.names] Status: Review Submitter: James Kanze Date: 11 Jan 2001
Paragraph 2 of 17.4.3.1.1 [lib.macro.names] 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 @@ -1330,15 +1073,32 @@ headers. The phrase would be perfectly appropriate for C, for example. In light of 17.4.4.1 [lib.res.on.headers] paragraph 1, however, it isn't stringent enough.
Proposed resolution:
-In paragraph 2 of 17.4.3.1.1 [lib.macro.names], 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."
+For 17.4.3.1.1 [lib.macro.names], replace the current wording, which reads:
+++ +Each name defined as a macro in a header is reserved to the + implementation for any use if the translation unit includes + the header.168)
-[Copenhagen: the general idea is clearly correct, but there is -concern about making sure that the two paragraphs in 17.4.3.1.1 [lib.macro.names] remain consistent. Nathan will provide new -wording.]
+A translation unit that includes a header shall not contain any + macros that define names declared or defined in that header. Nor shall + such a translation unit define macros for names lexically + identical to keywords.
+ +168) It is not permissible to remove a library macro definition by + using the #undef directive.
+
with the wording:
+ +++ +A translation unit that includes a standard library header shall not + #define or #undef names declared in any standard library header.
+ +A translation unit shall not #define or #undef names lexically + identical to keywords.
+
[Lillehammer: Beman provided new wording]
Section: 24.1.4 [lib.bidirectional.iterators], 24.1.5 [lib.random.access.iterators] Status: Open Submitter: John Potter Date: 22 Jan 2001
@@ -1440,247 +1200,11 @@ with a return type of convertible to T and operational semantics of *(a + n) = t. -Section: 27.6 [lib.iostream.format] Status: Open Submitter: Martin Sebor Date: 19 Mar 2001
--The descriptions of the constructors of basic_istream<>::sentry -(27.6.1.1.2 [lib.istream::sentry]) and basic_ostream<>::sentry -(27.6.2.3 [lib.ostream::sentry]) 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. -
- --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 195, since -the function performs an input operation which may fail. However, -issue 195 amends 27.6.1.1.2 [lib.istream::sentry], p2 to -clarify that the function should actually call setstate(failbit | -eofbit), so the sentence in p3 is redundant or even somewhat -contradictory. -
- --The same sentence that appears in 27.6.2.3 [lib.ostream::sentry], 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). -
- -Additional comments from Martin, who isn't comfortable with the - current proposed resolution (see c++std-lib-11530)
- --The istream::sentry ctor says nothing about how the function -deals with exemptions (27.6.1.1.2, p1 says that the class is -responsible for doing "exception safe"(*) prefix and suffix -operations but it doesn't explain what level of exception -safety the class promises to provide). The mockup example -of a "typical implementation of the sentry ctor" given in -27.6.1.1.2, p6, removed in ISO/IEC 14882:2003, doesn't show -exception handling, either. Since the ctor is not classified -as a formatted or unformatted input function, the text in -27.6.1.1, p1 through p4 does not apply. All this would seem -to suggest that the sentry ctor should not catch or in any -way handle exceptions thrown from any functions it may call. -Thus, the typical implementation of an istream extractor may -look something like [1]. -
- --The problem with [1] is that while it correctly sets ios::badbit -if an exception is thrown from one of the functions called from -the sentry ctor, if the sentry ctor reaches EOF while extracting -whitespace from a stream that has eofbit or failbit set in -exceptions(), it will cause an ios::failure to be thrown, which -will in turn cause the extractor to set ios::badbit. -
- --The only straightforward way to prevent this behavior is to -move the definition of the sentry object in the extractor -above the try block (as suggested by the example in 22.2.8, -p9 and also indirectly supported by 27.6.1.3, p1). See [2]. -But such an implementation will allow exceptions thrown from -functions called from the ctor to freely propagate to the -caller regardless of the setting of ios::badbit in the stream -object's exceptions(). -
- --So since neither [1] nor [2] behaves as expected, the only -possible solution is to have the sentry ctor catch exceptions -thrown from called functions, set badbit, and propagate those -exceptions if badbit is also set in exceptions(). (Another -solution exists that deals with both kinds of sentries, but -the code is non-obvious and cumbersome -- see [3].) -
- --Please note that, as the issue points out, current libraries -do not behave consistently, suggesting that implementors are -not quite clear on the exception handling in istream::sentry, -despite the fact that some LWG members might feel otherwise. -(As documented by the parenthetical comment here: -http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1480.html#309) -
- --Also please note that those LWG members who in Copenhagen -felt that "a sentry's constructor should not catch exceptions, -because sentries should only be used within (un)formatted input -functions and that exception handling is the responsibility of -those functions, not of the sentries," as noted here -http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1310.html#309 -would in effect be either arguing for the behavior described -in [1] or for extractors implemented along the lines of [3]. -
- --The original proposed resolution (Revision 25 of the issues -list) clarifies the role of the sentry ctor WRT exception -handling by making it clear that extractors (both library -or user-defined) should be implemented along the lines of -[2] (as opposed to [1]) and that no exception thrown from -the callees should propagate out of either function unless -badbit is also set in exceptions(). -
- - -[1] Extractor that catches exceptions thrown from sentry:
- --- -struct S { long i; }; - -istream& operator>> (istream &strm, S &s) -{ - ios::iostate err = ios::goodbit; - try { - const istream::sentry guard (strm, false); - if (guard) { - use_facet<num_get<char> >(strm.getloc ()) - .get (istreambuf_iterator<char>(strm), - istreambuf_iterator<char>(), - strm, err, s.i); - } - } - catch (...) { - bool rethrow; - try { - strm.setstate (ios::badbit); - rethrow = false; - } - catch (...) { - rethrow = true; - } - if (rethrow) - throw; - } - if (err) - strm.setstate (err); - return strm; -} --
[2] Extractor that propagates exceptions thrown from sentry:
- --- -istream& operator>> (istream &strm, S &s) -{ - istream::sentry guard (strm, false); - if (guard) { - ios::iostate err = ios::goodbit; - try { - use_facet<num_get<char> >(strm.getloc ()) - .get (istreambuf_iterator<char>(strm), - istreambuf_iterator<char>(), - strm, err, s.i); - } - catch (...) { - bool rethrow; - try { - strm.setstate (ios::badbit); - rethrow = false; - } - catch (...) { - rethrow = true; - } - if (rethrow) - throw; - } - if (err) - strm.setstate (err); - } - return strm; -} --
-[3] Extractor that catches exceptions thrown from sentry -but doesn't set badbit if the exception was thrown as a -result of a call to strm.clear(). -
- --- +istream& operator>> (istream &strm, S &s) -{ - const ios::iostate state = strm.rdstate (); - const ios::iostate except = strm.exceptions (); - ios::iostate err = std::ios::goodbit; - bool thrown = true; - try { - const istream::sentry guard (strm, false); - thrown = false; - if (guard) { - use_facet<num_get<char> >(strm.getloc ()) - .get (istreambuf_iterator<char>(strm), - istreambuf_iterator<char>(), - strm, err, s.i); - } - } - catch (...) { - if (thrown && state & except) - throw; - try { - strm.setstate (ios::badbit); - thrown = false; - } - catch (...) { - thrown = true; - } - if (thrown) - throw; - } - if (err) - strm.setstate (err); - - return strm; -} --
[Lillehammer: Real problem, but should be addressed as part of + iterator redesign]
-Proposed resolution:
-Remove the last sentence of 27.6.1.1.2 [lib.istream::sentry] p5 (but not - the footnote, which should be moved to the preceding sentence).
-Remove the last sentence of 27.6.2.3 [lib.ostream::sentry] p3 (but not - the footnote, which should be moved to the preceding sentence).
-Rationale:
-The LWG feels that no clarification of EH policy is necessary: the - standard is precise about which operations sentry's constructor - performs, and about which of those operations can throw. However, the - sentence at the end should be removed because it's redundant.
Section: 27.6.1.3 [lib.istream.unformatted] Status: Open Submitter: Howard Hinnant Date: 09 Oct 201
+Section: 27.6.1.3 [lib.istream.unformatted] Status: Review Submitter: Howard Hinnant Date: 09 Oct 2001
I think we have a defect.
According to lwg issue 60 which is now a dr, the @@ -1742,167 +1266,32 @@ modes than actual input. If we do really mean that it's unformatted input, it should behave the same way as other unformatted input. On the other hand, "principle of least surprise" is that seeking from EOF ought to be OK.
- -Dietmar: nothing should depend on eofbit. Eofbit should only be -examined by the user to determine why something failed.
- -[Taken from c++std-lib-8873, c++std-lib-8874, c++std-lib-8876]
-Proposed resolution:
-[Santa Cruz: On the one hand, it would clearly be silly to seek - to a non-EOF position without resetting eofbit. On the other hand, - having seek clear eofbit explicitly would set a major precedent: - there is currently no place where any of the flags are reset - without the user explicitly asking for them to be. This is the tip - of a general problem, that the various flags are stickier than many - users might expect. Bill, Gaby, and Howard will discuss this issue - and propose a resolution.]
- -Section: 22.2.1 [lib.category.ctype] Status: Open Submitter: Matt Austern Date: 23 Jan 2002
- -What should the following program print?
- -#include <locale> - #include <iostream> - - class my_ctype : public std::ctype<char> - { - typedef std::ctype<char> base; - public: - my_ctype(std::size_t refs = 0) : base(my_table, false, refs) - { - std::copy(base::classic_table(), base::classic_table() + base::table_size, - my_table); - my_table[(unsigned char) '_'] = (base::mask) (base::print | base::space); - } - private: - mask my_table[base::table_size]; - }; - - int main() - { - my_ctype ct; - std::cout << "isspace: " << ct.is(std::ctype_base::space, '_') << " " - << "isalpha: " << ct.is(std::ctype_base::alpha, '_') << std::endl; - } -- -
The goal is to create a facet where '_' is treated as whitespace.
- -On gcc 3.0, this program prints "isspace: 1 isalpha: 0". On -Microsoft C++ it prints "isspace: 1 isalpha: 1".
- --I believe that both implementations are legal, and the standard does not -give enough guidance for users to be able to use std::ctype's -protected interface portably.
- --The above program assumes that ctype_base::mask enumerators like -space and print are disjoint, and that the way to -say that a character is both a space and a printing character is to or -those two enumerators together. This is suggested by the "exposition -only" values in 22.2.1 [lib.category.ctype], but it is nowhere specified in -normative text. An alternative interpretation is that the more -specific categories subsume the less specific. The above program -gives the results it does on the Microsoft compiler because, on that -compiler, print has all the bits set for each specific -printing character class. -
- -From the point of view of std::ctype's public interface, there's no -important difference between these two techniques. From the point of -view of the protected interface, there is. If I'm defining a facet -that inherits from std::ctype<char>, I'm the one who defines the -value that table()['a'] returns. I need to know what combination of -mask values I should use. This isn't so very esoteric: it's exactly -why std::ctype has a protected interface. If we care about users -being able to write their own ctype facets, we have to give them a -portable way to do it. -
- --Related reflector messages: -lib-9224, lib-9226, lib-9229, lib-9270, lib-9272, lib-9273, lib-9274, -lib-9277, lib-9279. -
- -Issue 339 is related, but not identical. The -proposed resolution if issue 339 says that -ctype_base::mask must be a bitmask type. It does not say that the -ctype_base::mask elements are bitmask elements, so it doesn't -directly affect this issue.
- -More comments from Benjamin Kosnik, who believes that -that C99 compatibility essentially requires what we're -calling option 1 below.
- +Change 27.6.1.3 [lib.istream.unformatted] to:
--I think the C99 standard is clear, that isspace -> !isalpha. --------- - -#include <locale> -#include <iostream> - -class my_ctype : public std::ctype<char> -{ -private: - typedef std::ctype<char> base; - mask my_table[base::table_size]; - -public: - my_ctype(std::size_t refs = 0) : base(my_table, false, refs) - { - std::copy(base::classic_table(), base::classic_table() + base::table_size, - my_table); - mask both = base::print | base::space; - my_table[static_cast<mask>('_')] = both; - } -}; - -int main() -{ - using namespace std; - my_ctype ct; - cout << "isspace: " << ct.is(ctype_base::space, '_') << endl; - cout << "isprint: " << ct.is(ctype_base::print, '_') << endl; - - // ISO C99, isalpha iff upper | lower set, and !space. - // 7.5, p 193 - // -> looks like g++ behavior is correct. - // 356 -> bitmask elements are required for ctype_base - // 339 -> bitmask type required for mask - cout << "isalpha: " << ct.is(ctype_base::alpha, '_') << endl; -} -+Behaves as an unformatted input function (as described in 27.6.1.3, +paragraph 1), except that it does not count the number of characters +extracted, does not affect the value returned by subsequent calls to +gcount(), and does not examine the value returned by the sentry +object. After constructing a sentry object, if fail() != +true, executes rdbuf()->pubseekpos(pos). In +case of success, the function calls clear(). +In case of failure, the function calls setstate(failbit) +(which may throw ios_base::failure).
Proposed resolution:
-Informally, we have three choices:
-Either of the first two options is just as good from the standpoint -of portability. Either one will require some implementations to -change.
- -[ -More discussion is needed. Nobody likes option 3. Options 1 and 2 -are both controversial, 2 perhaps less so. Benjamin thinks that -option 1 is required for C99 compatibility. -]
+[Lillehammer: Matt provided wording.]
+Rationale:
+In C, fseek does clear EOF. This is probably what most users would + expect. We agree that having eofbit set should not deter a seek, + and that a successful seek should clear eofbit. Note + that fail() is true only if failbit + or badbit is set, so using !fail(), rather + than good(), satisfies this goal.
Section: 20.3.6.2 [lib.bind.1st] Status: Open Submitter: Andrew Demkin Date: 26 Apr 2002
+Section: 20.3.6.2 [lib.bind.1st] Status: Review Submitter: Andrew Demkin Date: 26 Apr 2002
The definition of bind1st() (20.3.6.2 [lib.bind.1st]) can result in the construction of an unsafe binding between incompatible pointer @@ -1939,156 +1328,18 @@ as a reinterpret_cast, thus masking the error.
The problem and proposed change also apply to 20.3.6.4 [lib.bind.2nd].
Proposed resolution:
--The simplest and most localized change to prevent such errors is to -require bind1st() use a static_cast expression rather than the -functional-style conversion; that is, have bind1st() return: -
-binder1st<Operation>( op, - static_cast<typename Operation::first_argument_type>(x)). -+
Add this sentence to the end of 20.3.6 [lib.binders]/1: + "Binders bind1st and bind2nd are deprecated in + favor of std::tr1::bind."
--A more agressive solution is to change the semantics of -functional-style conversions to not permit a reinterpret_cast. For -contexts that require the semantics of reinterpret_cast, the language -may want to require the use of an explicit cast expression such as -'(T) x' or 'reinterpret_cast<T>(x)' and limit the behavior of -the functional notation to match statically-checked and standard -conversions (as defined by 5.2.9 and 4.10, etc.). Although changing -the semantics of functional-style conversions may seem drastic and -does have language-wide ramifications, it has the benefit of better -unifying the conversion rules for user defined types and built-in -types, which can be especially important for generic template -programming. -
- -[Santa Cruz: it's clear that a function-style cast is - wrong. Maybe a static cast would be better, or maybe no cast at - all. Jeremy will check with the original author of this part - of the Standard and will see what the original intent was.]
+(Notes to editor: (1) when and if tr1::bind is incorporated into + the standard, "std::tr1::bind" should be changed to "std::bind". (2) + 20.3.6 should probably be moved to Annex D.
+Rationale:
+There is no point in fixing bind1st and bind2nd. tr1::bind is a + superior solution. It solves this problem and others.
Section: 27 [lib.input.output] Status: Open Submitter: Walter Brown, Marc Paterno Date: 10 May 2002
--The following member functions are declared const, yet return non-const -pointers. We believe they are should be changed, because they allow code -that may surprise the user. See document N1360 for details and -rationale. -
- -[Santa Cruz: the real issue is that we've got const member -functions that return pointers to non-const, and N1360 proposes -replacing them by overloaded pairs. There isn't a consensus about -whether this is a real issue, since we've never said what our -constness policy is for iostreams. N1360 relies on a distinction -between physical constness and logical constness; that distinction, or -those terms, does not appear in the standard.]
- -Proposed resolution:
-In 27.4.4 and 27.4.4.2
-Replace
-basic_ostream<charT,traits>* tie() const; --
with
-basic_ostream<charT,traits>* tie(); - const basic_ostream<charT,traits>* tie() const; -- -
and replace
-basic_streambuf<charT,traits>* rdbuf() const; --
with
-basic_streambuf<charT,traits>* rdbuf(); - const basic_streambuf<charT,traits>* rdbuf() const; -- -
In 27.5.2 and 27.5.2.3.1
-Replace
-char_type* eback() const; --
with
-char_type* eback(); - const char_type* eback() const; -- -
Replace
-char_type gptr() const; --
with
-char_type* gptr(); - const char_type* gptr() const; -- -
Replace
-char_type* egptr() const; --
with
-char_type* egptr(); - const char_type* egptr() const; -- -
In 27.5.2 and 27.5.2.3.2
-Replace
-char_type* pbase() const; --
with
-char_type* pbase(); - const char_type* pbase() const; -- -
Replace
-char_type* pptr() const; --
with
-char_type* pptr(); - const char_type* pptr() const; -- -
Replace
-char_type* epptr() const; --
with
-char_type* epptr(); - const char_type* epptr() const; -- -
In 27.7.2, 27.7.2.2, 27.7.3 27.7.3.2, 27.7.4, and 27.7.6
-Replace
-basic_stringbuf<charT,traits,Allocator>* rdbuf() const; --
with
-basic_stringbuf<charT,traits,Allocator>* rdbuf(); - const basic_stringbuf<charT,traits,Allocator>* rdbuf() const; -- -
In 27.8.1.5, 27.8.1.7, 27.8.1.8, 27.8.1.10, 27.8.1.11, and 27.8.1.13
-Replace
-basic_filebuf<charT,traits>* rdbuf() const; --
with
-basic_filebuf<charT,traits>* rdbuf(); - const basic_filebuf<charT,traits>* rdbuf() const; --
Section: 21.3.5.6 [lib.string::replace] Status: Open Submitter: Beman Dawes Date: 3 Jun 2002
--21.3.5.6 [lib.string::replace] basic_string::replace, second -signature, given in paragraph 1, has two "Throws" paragraphs (3 and -5). -
- --In addition, the second "Throws" paragraph (5) includes specification -(beginning with "Otherwise, the function replaces ...") that should be -part of the "Effects" paragraph. -
-Proposed resolution:
-[This is a typo that escalated. It's clear that what's in the - Standard is wrong. It's less clear what the fix ought to be. - Someone who understands string replace well needs to work on - this.]
-Section: 27.3 [lib.iostream.objects] Status: Open Submitter: Ruslan Abdikeev Date: 8 Jul 2002
+Section: 27.3 [lib.iostream.objects] Status: Review Submitter: Ruslan Abdikeev Date: 8 Jul 2002
Is it safe to use standard iostream objects from constructors of static objects? Are standard iostream objects constructed and are @@ -2154,31 +1405,17 @@ mention of an _instance_ of ios_base::Init in Standard.
Proposed resolution:
-[Redmond: This still isn't precise enough. We need to give - users some guarantees, i.e. "if you do X, then you are guaranteed - that you will see behavior Y." We should guarantee that stream - objects are constructed before a static constructor if (1) - <iostream> is #included before the relevant static object; or - (2) the user explicitly constructs an ios_base::Init object before - calling that constuctor.]
- -Add to [lib.iostream.objects], p2, immediately before the last sentence +
Add to 27.3 [lib.iostream.objects], p2, immediately before the last sentence of the paragraph, the following two sentences:
-It is implementation-defined whether the header <iostream> defines -an ios_base::Init object or not. If it does not, an implementation -must specify the means of achieving safe access to the standard -objects for input and output during program startup. +If a translation unit includes <iostream>, or explicitly +constructs an ios_base::Init object, dynamic initialization of objects +later in that translation unit may assume that these stream objects +have been constructed and destructors may assume that these stream +objects have not yet been destroyed.-
[Santa Cruz: The LWG is leaning toward NAD. There isn't any -normative wording saying that the Init scheme will be used, but that -is probably intentional. Implementers use dirty tricks for iostream -initialization, and doing it portably is somewhere between difficult -and impossible. Too much constraint in this area is dangerous, and if -we are to make any changes it would probably be more appropriate -for them to be nonnormative. Summer '04 mid-meeting mailing: Martin -provided wording for resolution and rationale.]
+[Lillehammer: Matt provided wording.]
Rationale:
The original proposed resolution unconditionally required @@ -2192,34 +1429,10 @@ is no need to require implementations to document the name of the object.
-The new proposed resolution specifies that implementations may -(but need not) define an ios_base::Init object, while requiring -them to document whether they do or not, and if not, to document -how portable programs achieve safe access to the 8 standard iostream -objects during program startup (3.6)(*). The intent is that if an -implementation documents that <iostream> defines an ios_base::Init -object, it implies that the header must be #included before any -references to the standard iostream objects. Otherwise, if an -implementation does not define an ios_base::Init object in -<iostream> it must either assure and document that the standard -iostream objects are safely accessible at startup, or specify what -a portable program must do to safely access them (e.g., it may -require that a program define an ios_base::Init object before -doing so, or that it call ios::sync_with_stdio(), etc.). -
- --(*) Note that the term startup is broader than the term "Constructors -and destructors for static objects" used in Footnote 265 since the -former includes other functions besides constructors and destructors, -including the following example: -
-int foo () { return (std::cout << "foo()\n").rdstate (); } - int i = foo (); - int main () { return i; } -+The new proposed resolution gives users guidance on what they need to +do to ensure that stream objects are constructed during startup.
Section: 23.1 [lib.container.requirements] Status: Open Submitter: Frank Compagner Date: 20 Jul 2002
+Section: 23.1 [lib.container.requirements] Status: Review Submitter: Frank Compagner Date: 20 Jul 2002
The requirements for multiset and multimap containers (23.1 [lib.containers.requirements], 23.1.2 [lib.associative.reqmnts], @@ -2271,22 +1484,41 @@ be hard to track down by users. This would also make the need for an erase_if() member function that much greater.
-This issue is somewhat related to LWG issue 130.
- -[Santa Cruz: More people need to look at this. Much user code - may assume stability. On the other hand, it seems drastic to add a - new requirement now.]
+This issue is somewhat related to LWG issue 130.
Proposed resolution:
+ +Add the following to the end of 23.1.2 [lib.associative.reqmts] paragraph 4: +"For set and map, insertand erase + are stable: they preserve the relative ordering of equivalent + elements.
+ +[Lillehammer: Matt provided wording]
+[Joe Gottman points out that the provided wording does not address +multimap and multiset. N1780 also addresses this issue and suggests +wording.]
+ +Rationale:
+The LWG agrees that this guarantee is necessary for common user + idioms to work, and that all existing implementations provide this + property. Note that this resolution guarantees stability for + multimap and multiset, not for all associative containers in + general.
Section: 27.7.1.3 [lib.stringbuf.virtuals] Status: Open Submitter: Ray Lischner Date: 14 Aug 2002
+Section: 27.7.1.3 [lib.stringbuf.virtuals] Status: Review Submitter: Ray Lischner Date: 14 Aug 2002
In Section 27.7.1.3 [lib.stringbuf.virtuals], Table 90, the implication is that the four conditions should be mutually exclusive, but they are not. -The first two cases, as written, are subcases of the third. I think it -would be clearer if the conditions were rewritten as follows: +The first two cases, as written, are subcases of the third.
+ ++As written, it is unclear what should be the result if cases 1 and 2 +are both true, but case 3 is false.
+Proposed resolution:
+ +Rewrite these conditions as:
-(which & (ios_base::in|ios_base::out)) == ios_base::in @@ -2305,19 +1537,9 @@ would be clearer if the conditions were rewritten as follows:
Otherwise
-As written, it is unclear what should be the result if cases 1 & 2 -are true, but case 3 is false, e.g., -
- -- seekoff(0, ios_base::cur, ios_base::in | ios_base::out) -- -
[Santa Cruz: The ambiguity seems real. We need to do a survey of -implementations before we decide on a solution.]
- -Proposed resolution:
+Rationale:
+It's clear what we wanted to say, we just failed to say it. This + fixes it.
Section: 22.2.1.5 [lib.locale.codecvt] Status: Open Submitter: Martin Sebor Date: 30 Aug 2002
@@ -2416,79 +1638,22 @@ which would make perfect sense, since, as far as I understand it, partial can only occur if (from_next != from_end)?
Proposed resolution:
--To address these issues, I propose that paragraphs 2, 3, and 4 -be rewritten as follows. The proposal incorporates the accepted -resolution of lwg issue 19. -
--2- Effects: Converts characters in the range of source elements - [from, from_end), placing the results in sequential positions - starting at destination to. Converts no more than (from_end from) - source elements, and stores no more than (to_limit to) - destination elements. - - Stops if it encounters a sequence of source elements it cannot - convert to a valid destination character. It always leaves the - from_next and to_next pointers pointing one beyond the last - element successfully converted. - - [Note: If returns noconv, internT and externT are the same type - and the converted sequence is identical to the input sequence - [from, from_next). to_next is set equal to to, the value of - state is unchanged, and there are no changes to the values in - [to, to_limit). --end note] - --3- Notes: Its operations on state are unspecified. - [Note: This argument can be used, for example, to maintain shift - state, to specify conversion options (such as count only), or to - identify a cache of seek offsets. --end note] - --4- Returns: An enumeration value, as summarized in Table 53: - - Table 53 -- do_in/do_out result values - - Value Meaning - +---------+----------------------------------------------------+ - | ok | successfully completed the conversion of all | - | | complete characters in the source range | - +---------+----------------------------------------------------+ - | partial | the characters in the source range would, after | - | | conversion, require space greater than that | - | | available in the destination range | - +---------+----------------------------------------------------+ - | error | encountered either a sequence of elements in the | - | | source range forming a valid source character that | - | | could not be converted to a destination character, | - | | or a sequence of elements in the source range that | - | | could not possibly form a valid source character | - +---------+----------------------------------------------------+ - | noconv | internT and externT are the same type, and input | - | | sequence is identical to converted sequence | - +---------+----------------------------------------------------+ - - A return value of partial, i.e., if (from_next != from_end), - indicates that either the destination sequence has not absorbed - all the available destination elements, or that additional - source elements are needed before another destination character - can be produced. --
[Santa Cruz: The LWG agrees that this is an important issue and -that this general direction is probably correct. Dietmar, Howard, -PJP, and Matt will review this wording.]
- -[Kona: this isn't quite right. (a) the description of noconv is -too vague, both in the existing standard and in the current proposed -resolution; (b) the description of what noconv means should be -normative; (c) the phrase "partial, i.e. if from_next != from_end" -isn't quite right, because those are two separate cases, it's possible -to get partial either form insufficient input or from insufficient -space in the output buffer. The big problem is that the standard is -written with the assumption of 1->N conversion in mind, not M->N. -Bill, Howard, and Martin will provide new wording. -]
+[Lillehammer: Defer for the moment, but this really needs to be + fixed. Right now, the description of codecvt is too vague for it to + be a useful contract between providers and clients of codecvt + facets. (Note that both vendors and users can be both providers and + clients of codecvt facets.) The major philosophical issue is whether + the standard should only describe mappings that take a single wide + character to multiple narrow characters (and vice versa), or whether + it should describe fully general N-to-M conversions. When the + original standard was written only the former was contemplated, but + today, in light of the popularity of utf8 and utf16, that doesn't + seem sufficient for C++0x. Bill supports general N-to-M conversions; + we need to make sure Martin and Howard agree.]
+Section: 25.3.3.3 [lib.equal.range] Status: Open Submitter: Hans Bos Date: 18 Oct 2002
+Section: 25.3.3.3 [lib.equal.range] Status: Review Submitter: Hans Bos Date: 18 Oct 2002
Section 25.3.3.3 [lib.equal.range] states that at most 2 * log(last - first) + 1 @@ -2526,14 +1691,25 @@ have log(distance) characteristics when at most match is found in the range but 2log(distance) + 4 for the worst case).
-[Santa Cruz: The issue is real, but of greater scope than just -equal_range: it affects all of the binary search algorithms. What is -the complexity supposed to be for ranges of 0 or 1 elements? What -base are we using for the logarithm? Are these bounds supposed to be -exact, or asymptotic? (If the latter, of course, then none of the -other questions matter.)]
-Proposed resolution:
+In 25.3.3.1 [lib.lower.bound]/4, change log(last - first) + 1 +to log2(last - first) + O(1).
+ +In 25.3.3.2 [lib.upper.bound]/4, change log(last - first) + 1 +to log2(last - first) + O(1).
+ +In 25.3.3.3 [lib.equal.range]/4, change 2*log(last - first) + 1 +to 2*log2(last - first) + O(1).
+ +[Matt provided wording]
+Rationale:
+The LWG considered just saying O(log n) for all three, but +Ê decided that threw away too much valuable information.Ê The fact +Ê that lower_bound is twice as fast as equal_range is important. +Ê However, it's better to allow an arbitrary additive constant than to +Ê specify an exact count.Ê An exact count would have to +Ê involve floor or ceil.Ê It would be too easy to +Ê get this wrong, and don't provide any substantial value for users.
Section: 17 [lib.library] Status: Open Submitter: Matt Austern Date: 23 Oct 2002
@@ -2571,57 +1747,6 @@ into references? References aren't copy constructible, so this should not be allowed. ]
Section: 24.4.1.3.11 [lib.reverse.iter.opindex] Status: Ready Submitter: Matt Austern Date: 23 Oct 2002
-In 24.4.1.3.11 [lib.reverse.iter.opindex], reverse_iterator<>::operator[] -is specified as having a return type of reverse_iterator::reference, -which is the same as iterator_traits<Iterator>::reference. -(Where Iterator is the underlying iterator type.)
- -The trouble is that Iterator's own operator[] doesn't - necessarily have a return type - of iterator_traits<Iterator>::reference. Its - return type is merely required to be convertible - to Iterator's value type. The return type specified for - reverse_iterator's operator[] would thus appear to be impossible.
- -With the resolution of issue 299, the type of - a[n] will continue to be required (for random access - iterators) to be convertible to the value type, and also a[n] = - t will be a valid expression. Implementations of - reverse_iterator will likely need to return a proxy from - operator[] to meet these requirements. As mentioned in the - comment from Dave Abrahams, the simplest way to specify that - reverse_iterator meet this requirement to just mandate - it and leave the return type of operator[] unspecified.
- -Proposed resolution:
- -In 24.4.1.2 [lib.reverse.iter.requirements] change:
- --- -reference operator[](difference_type n) const; --
to:
- --- - - - -unspecified operator[](difference_type n) const; // see lib.random.access.iterators --
[ -Comments from Dave Abrahams: IMO we should resolve 386 by just saying - that the return type of reverse_iterator's operator[] is - unspecified, allowing the random access iterator requirements to - impose an appropriate return type. If we accept 299's proposed - resolution (and I think we should), the return type will be - readable and writable, which is about as good as we can do. -]
-Section: 26.2 [lib.complex.numbers] Status: Open Submitter: Gabriel Dos Reis Date: 8 Nov 2002
The absence of explicit description of std::complex<T> layout @@ -2827,7 +1952,7 @@ functions should be changed as proposed below.
Rationale:
Section: 23.3.5.1 [lib.bitset.cons] Status: Open Submitter: Martin Sebor Date: 5 Jan 2003
+Section: 23.3.5.1 [lib.bitset.cons] Status: Open Submitter: Martin Sebor Date: 5 Jan 2003
23.3.5.1, p6 [lib.bitset.cons] talks about a generic character
having the value of 0 or 1 but there is no definition of what
@@ -3107,29 +2232,6 @@ in 13.5.6 406. vector::insert(s) exception safety
Section: 23.2.4.3 [lib.vector.modifiers] Status: Ready Submitter: Dave Abrahams Date: 27 Apr 2003
--There is a possible defect in the standard: the standard text was -never intended to prevent arbitrary ForwardIterators, whose operations -may throw exceptions, from being passed, and it also wasn't intended -to require a temporary buffer in the case where ForwardIterators were -passed (and I think most implementations don't use one). As is, the -standard appears to impose requirements that aren't met by any -existing implementation. -
-Proposed resolution:
-Replace 23.2.4.3 [lib.vector.modifiers] paragraph 1 with:
-- 1- Notes: Causes reallocation if the new size is greater than the - old capacity. If no reallocation happens, all the iterators and - references before the insertion point remain valid. If an exception - is thrown other than by the copy constructor or assignment operator - of T or by any InputIterator operation there are no effects. -- -
[We probably need to say something similar for deque.]
-Section: 24.1 [lib.iterator.requirements] Status: Open Submitter: Nathan Myers Date: 3 June 2003
@@ -3254,126 +2356,6 @@ constructed pointers are required to be copyable; if not, it would be wrong to impose so strict a requirement for iterators. ]
-Section: 27.8.1.7 [lib.ifstream.members], 27.8.1.10 [lib.ofstream.members] Status: Ready Submitter: Nathan Myers Date: 3 June 2003
--A strict reading of 27.8.1 [lib.fstreams] shows that opening or -closing a basic_[io]fstream does not affect the error bits. This -means, for example, that if you read through a file up to EOF, and -then close the stream and reopen it at the beginning of the file, -the EOF bit in the stream's error state is still set. This is -counterintuitive. -
--The LWG considered this issue once before, as issue 22, -and put in a footnote to clarify that the strict reading was indeed -correct. We did that because we believed the standard was -unambiguous and consistent, and that we should not make architectural -changes in a TC. Now that we're working on a new revision of the -language, those considerations no longer apply. -
-Proposed resolution:
- -Change 27.8.1.7 [lib.ifstream.members], para. 3 from:
- --Calls rdbuf()->open(s,mode|in). If that function returns a null -pointer, calls setstate(failbit) (which may throw ios_base::failure -[Footnote: (lib.iostate.flags)]. -- -
to:
- -Calls rdbuf()->open(s,mode|in). If that function returns -a null pointer, calls setstate(failbit) (which may throw -ios_base::failure [Footnote: (lib.iostate.flags)), else calls clear(). -- -
Change 27.8.1.10 [lib.ofstream.members], para. 3 from:
- -Calls rdbuf()->open(s,mode|out). If that function -returns a null pointer, calls setstate(failbit) (which may throw -ios_base::failure [Footnote: (lib.iostate.flags)). -- -
to:
- -Calls rdbuf()->open(s,mode|out). If that function -returns a null pointer, calls setstate(failbit) (which may throw -ios_base::failure [Footnote: (lib.iostate.flags)), else calls clear(). -- -
Change 27.8.1.13 [lib.fstream.members], para. 3 from:
- -Calls rdbuf()->open(s,mode), If that function returns a -null pointer, calls setstate(failbit), (which may throw -ios_base::failure). (lib.iostate.flags) ) -- -
to:
- -Calls rdbuf()->open(s,mode), If that function returns a -null pointer, calls setstate(failbit), (which may throw -ios_base::failure). (lib.iostate.flags) ), else calls clear(). -- - - -
[Kona: the LWG agrees this is a good idea. Post-Kona: Bill -provided wording. He suggests having open, not close, clear the error -flags.]
- -[Post-Sydney: Howard provided a new proposed resolution. The - old one didn't make sense because it proposed to fix this at the - level of basic_filebuf, which doesn't have access to the stream's - error state. Howard's proposed resolution fixes this at the level - of the three fstream class template instead.]
- -Section: 27.6.1.2.3 [lib.istream::extractors] Status: Ready Submitter: Bo Persson Date: 13 Jul 2003
--The second sentence of the proposed resolution says: -
- --"If it inserted no characters because it caught an exception thrown -while extracting characters from sb and ..." -
- --However, we are not extracting from sb, but extracting from the -basic_istream (*this) and inserting into sb. I can't really tell if -"extracting" or "sb" is a typo. -
- -[ -Sydney: Definitely a real issue. We are, indeed, extracting characters -from an istream and not from sb. The problem was there in the FDIS and -wasn't fixed by issue 64. Probably what was intended was -to have *this instead of sb. We're talking about the exception flag -state of a basic_istream object, and there's only one basic_istream -object in this discussion, so that would be a consistent -interpretation. (But we need to be careful: the exception policy of -this member function must be consistent with that of other -extractors.) PJP will provide wording. -]
- -Proposed resolution:
-Change the sentence from:
- --If it inserted no characters because it caught an exception thrown -while extracting characters from sb and failbit is on in exceptions(), -then the caught exception is rethrown. -- -
to:
- --If it inserted no characters because it caught an exception thrown -while extracting characters from *this and failbit is on in exceptions(), -then the caught exception is rethrown. -
Section: 18.2.2 [lib.c.limits] Status: Open Submitter: Martin Sebor Date: 18 Sep 2003
@@ -3653,7 +2635,8 @@ Constructs an independent copy of sb as if with sb.str(), and with the openmode getloc() == sb.getloc() -
Note: The only requirement on epptr() is that it point beyond the +
+Note: The only requirement on epptr() is that it point beyond the initialized range if an output sequence exists. There is no requirement that epptr() - pbase() == sb.epptr() - sb.pbase().
@@ -3721,7 +2704,7 @@ basic_filebuf.Section: 17.4.3.1 [lib.reserved.names] Status: Open Submitter: Martin Sebor Date: 18 Sep 2003
+Section: 17.4.3.1 [lib.reserved.names] Status: Open Submitter: Martin Sebor Date: 18 Sep 2003
It has been suggested that 17.4.3.1, p1 may or may not allow programs to explicitly specialize members of standard templates on user-defined types. @@ -3948,2822 +2931,1388 @@ object (e.g., slice (2, 1, 1) for a valarray of size 1).
[pre-Sydney: Howard argues for option 3 in n1599.]
Section: 23.3.5.2 [lib.bitset.members] Status: Ready Submitter: Martin Sebor Date: 15 Oct 2003
+Section: 24.1 [lib.iterator.requirements], 23.1 [lib.container.requirements] Status: Open Submitter: Andy Koenig Date: 16 Dec 2003
-It has been pointed out a number of times that the bitset to_string() member -function template is tedious to use since callers must explicitly specify the -entire template argument list (3 arguments). At least two implementations -provide a number of overloads of this template to make it easier to use. +What requirements does the standard place on equality comparisons between +iterators that refer to elements of different containers. For example, if +v1 and v2 are empty vectors, is v1.end() == v2.end() allowed to yield true? +Is it allowed to throw an exception?
-Proposed resolution:
-In order to allow callers to specify no template arguments at all, just the -first one (charT), or the first 2 (charT and traits), in addition to all -three template arguments, add the following three overloads to both the -interface (declarations only) of the class template bitset as well as to -section 23.3.5.2, immediately after p34, the Returns clause of the existing -to_string() member function template:
-template <class charT, class traits> - basic_string<charT, traits, allocator<charT> > - to_string () const; - - -34.1- Returns: to_string<charT, traits, allocator<charT> >(). - - template <class charT> - basic_string<charT, char_traits<charT>, allocator<charT> > - to_string () const; - - -34.2- Returns: to_string<charT, char_traits<charT>, allocator<charT> >(). - - basic_string<char, char_traits<char>, allocator<char> > - to_string () const; - - -34.3- Returns: to_string<char, char_traits<char>, allocator<char> >(). -+
+The standard appears to be silent on both questions. +
+Proposed resolution:
-[Kona: the LWG agrees that this is an improvement over the - status quo. Dietmar thought about an alternative using a proxy - object but now believes that the proposed resolution above is the - right choice. +
[Sydney: The intention is that comparing two iterators from +different containers is undefined, but it's not clear if we say that, +or even whether it's something we should be saying in clause 23 or in +clause 24. Intuitively we might want to say that equality is defined +only if one iterator is reachable from another, but figuring out how +to say it in any sensible way is a bit tricky: reachability is defined +in terms of equality, so we can't also define equality in terms of +reachability. ]
Section: 23.1.1 [lib.sequence.reqmts] Status: Ready Submitter: Howard Hinnant Date: 20 Oct 2003
- -Section 23.1.1 [lib.sequence.reqmts], paragraphs 9-11, fixed up the problem -noticed with statements like:
-vector<int> v(10, 1); -- -
The intent of the above statement was to construct with:
-vector(size_type, const value_type&); +454. basic_filebuf::open should accept wchar_t names
Section: 27.8.1.3 [lib.filebuf.members] Status: Open Submitter: Bill Plauger Date: 30 Jan 2004
+basic_filebuf *basic_filebuf::open(const char *, ios_base::open_mode);-but early implementations failed to compile as they bound to:
-template <class InputIterator> -vector(InputIterator f, InputIterator l); --instead.
+should be supplemented with the overload:
-Paragraphs 9-11 say that if InputIterator is an integral type, then the -member template constructor will have the same effect as:
-vector<static_cast<size_type>(f), static_cast<value_type>(l)); +basic_filebuf *basic_filebuf::open(const wchar_t *, ios_base::open_mode);-(and similarly for the other member template functions of sequences).
- -There is also a note that describes one implementation technique:
-- One way that sequence implementors can satisfy this requirement is to - specialize the member template for every integral type. --This might look something like:
--+template <class T> -struct vector -{ - typedef unsigned size_type; +-+Depending on the operating system, one of these forms is fundamental and +the other requires an implementation-defined mapping to determine the +actual filename. +
- explicit vector(size_type) {} - vector(size_type, const T&) {} +[Sydney: Yes, we want to allow wchar_t filenames. Bill will + provide wording.]
- template <class I> - vector(I, I); +Proposed resolution:
- // ... -}; +Change from:
++-template <> -template <> -vector<int>::vector(int, int) { ... } +basic_filebuf<charT,traits>* open( + const char* s, + ios_base::openmode mode ); +-template <class T> -template <class I> -vector<T>::vector(I, I) { ... } ++Effects: If is_open() != false, returns a null pointer. +Otherwise, initializes the filebuf as required. It then +opens a file, if possible, whose name is the NTBS s ("as if" +by calling std::fopen(s,modstr)).
+to:
-template <> -template <> -vector<int>::vector(unsigned, unsigned) { ... } ++-basic_filebuf<charT,traits>* open( + const char* s, + ios_base::openmode mode ); -// ... +basic_filebuf<charT,traits>* open( + const wchar_t* ws, + ios_base::openmode mode );-Label this solution 'A'.
++Effects: If is_open() != false, returns a null pointer. +Otherwise, initializes the filebuf as required. It then +opens a file, if possible, whose name is the NTBS s ("as if" +by calling std::fopen(s,modstr)). +For the second signature, the NTBS s is determined from the +WCBS ws in an implementation-defined manner. +
-The standard also says:
-- Less cumbersome implementation techniques also exist. --A popular technique is to not specialize as above, but instead catch -every call with the member template, detect the type of InputIterator, -and then redirect to the correct logic. Something like: +(NOTE: For a system that "naturally" represents a filename +as a WCBS, the NTBS s in the first signature may instead +be mapped to a WCBS; if so, it follows the same mapping +rules as the first argument to open.)
---template <class T> -template <class I> -vector<T>::choose_init(I f, I l, int2type<false>) -{ - // construct with iterators -} +template <class T> -template <class I> -vector<T>::vector(I f, I l) -{ - choose_init(f, l, int2type<is_integral<I>::value>()); -} +Rationale:
++Slightly controversial, but by a 7-1 straw poll the LWG agreed to move +this to Ready. The controversy was because the mapping between wide +names and files in a filesystem is implementation defined. The +counterargument, which most but not all LWG members accepted, is that +the mapping between narrow files names and files is also +implemenation defined.
-template <class T> -template <class I> -vector<T>::choose_init(I f, I l, int2type<true>) -{ - size_type sz = static_cast<size_type>(f); - value_type v = static_cast<value_type>(l); - // construct with sz,v -} -[Lillehammer: Moved back to "open" status, at Beman's urging. +(1) Why just basic_filebuf, instead of also basic_fstream (and +possibly other things too). (2) Why not also constructors that take +std::basic_string? (3) We might want to wait until we see Beman's +filesystem library; we might decide that it obviates this.]
-Label this solution 'B'.
+
+456. Traditional C header files are overspecified
Section: 17.4.1.2 [lib.headers] Status: Open Submitter: Bill Plauger Date: 30 Jan 2004
-Both of these solutions solve the case the standard specifically -mentions:
-vector<int> v(10, 1); // ok, vector size 10, initialized to 1 -+The C++ Standard effectively requires that the traditional C headers +(of the form <xxx.h>) be defined in terms of the newer C++ +headers (of the form <cxxx>). Clauses 17.4.1.2/4 and D.5 combine +to require that:
+ +
-However, (and here is the problem), the two solutions have different -behavior in some cases where the value_type of the sequence is not an -integral type. For example consider: +The rules were left in this form despited repeated and heated objections +from several compiler vendors. The C headers are often beyond the direct +control of C++ implementors. In some organizations, it's all they can do +to get a few #ifdef __cplusplus tests added. Third-party library vendors +can perhaps wrap the C headers. But neither of these approaches supports +the drastic restructuring required by the C++ Standard. As a result, it is +still widespread practice to ignore this conformance requirement, nearly +seven years after the committee last debated this topic. Instead, what is +often implemented is:
-+ +pair<char, char> p('a', 'b'); - vector<vector<pair<char, char> > > d('a', 'b'); -
+The practical benefit for implementors with the second approach is that +they can use existing C library headers, as they are pretty much obliged +to do. The practical cost for programmers facing a mix of implementations +is that they have to assume weaker rules:
+ +-The second line of this snippet is likely an error. Solution A catches -the error and refuses to compile. The reason is that there is no -specialization of the member template constructor that looks like: +There also exists the possibility of subtle differences due to +Koenig lookup, but there are so few non-builtin types defined in the C +headers that I've yet to see an example of any real problems in this +area.
-template <> -template <> -vector<vector<pair<char, char> > >::vector(char, char) { ... } -
-So the expression binds to the unspecialized member template -constructor, and then fails (compile time) because char is not an -InputIterator. +It is worth observing that the rate at which programmers fall afoul of +these differences has remained small, at least as measured by newsgroup +postings and our own bug reports. (By an overwhelming margin, the +commonest problem is still that programmers include <string> and can't +understand why the typename string isn't defined -- this a decade after +the committee invented namespace std, nominally for the benefit of all +programmers.)
-Solution B compiles the above example though. 'a' is casted to an -unsigned integral type and used to size the outer vector. 'b' is -static casted to the inner vector using it's explicit constructor: +We should accept the fact that we made a serious mistake and rectify it, +however belatedly, by explicitly allowing either of the two schemes for +declaring C names in headers.
-explicit vector(size_type n); -+
[Sydney: This issue has been debated many times, and will + certainly have to be discussed in full committee before any action + can be taken. However, the preliminary sentiment of the LWG was in + favor of the change. (6 yes, 0 no, 2 abstain) Robert Klarer + suggests that we might also want to undeprecate the + C-style .h headers.]
+Proposed resolution:
+Section: 24.1.5 [lib.random.access.iterators] Status: Open Submitter: Daniel Frey Date: 27 Feb 2004
-and so you end up with a static_cast<size_type>('a') by -static_cast<size_type>('b') matrix. +In 24.1.5 [lib.random.access.iterators], table 76 the operational +semantics for the expression "r -= n" are defined as "return r += -n". +This means, that the expression -n must be valid, which is not the case +for unsigned types.
+[ +Sydney: Possibly not a real problem, since difference type is required +to be a signed integer type. However, the wording in the standard may +be less clear than we would like. +]
+ +Proposed resolution:
-It is certainly possible that this is what the coder intended. But the -explicit qualifier on the inner vector has been thwarted at any rate. +To remove this limitation, I suggest to change the +operational semantics for this column to:
+
+ { Distance m = n;
+ if (m >= 0)
+ while (m--) --r;
+ else
+ while (m++) ++r;
+ return r; }
+
+
+Section: 22.2.2.1.2 [lib.facet.num.get.virtuals] Status: Open Submitter: Martin Sebor Date: 16 Mar 2004
+When parsing strings of wide-character digits, the standard + requires the library to widen narrow-character "atoms" and compare + the widened atoms against the characters that are being parsed. + Simply narrowing the wide characters would be far simpler, and + probably more efficient. The two choices are equivalent except in + convoluted test cases, and many implementations already ignore the + standard and use narrow instead of widen.
-The standard is not clear whether the expression: +First, I disagree that using narrow() instead of widen() would +necessarily have unfortunate performance implications. A possible +implementation of narrow() that allows num_get to be implemented +in a much simpler and arguably comparably efficient way as calling +widen() allows, i.e. without making a virtual call to do_narrow every +time, is as follows:
-vector<vector<pair<char, char> > > d('a', 'b'); +inline char ctype<wchar_t>::narrow (wchar_t wc, char dflt) const + { + const unsigned wi = unsigned (wc); + + if (wi > UCHAR_MAX) + return typeid (*this) == typeid (ctype<wchar_t>) ? + dflt : do_narrow (wc, dflt); + + if (narrow_ [wi] < 0) { + const char nc = do_narrow (wc, dflt); + if (nc == dflt) + return dflt; + narrow_ [wi] = nc; + } + + return char (narrow_ [wi]); + }-(and similar expressions) are: +Second, I don't think the change proposed in the issue (i.e., to use +narrow() instead of widen() during Stage 2) would be at all +drastic. Existing implementations with the exception of libstdc++ +currently already use narrow() so the impact of the change on programs +would presumably be isolated to just a single implementation. Further, +since narrow() is not required to translate alternate wide digit +representations such as those mentioned in issue 303 to +their narrow equivalents (i.e., the portable source characters '0' +through '9'), the change does not necessarily imply that these +alternate digits would be treated as ordinary digits and accepted as +part of numbers during parsing. In fact, the requirement in 22.2.1.1.2 [lib.locale.ctype.virtuals], p13 forbids narrow() to translate an alternate +digit character, wc, to an ordinary digit in the basic source +character set unless the expression +(ctype<charT>::is(ctype_base::digit, wc) == true) holds. This in +turn is prohibited by the C standard (7.25.2.1.5, 7.25.2.1.5, and +5.2.1, respectively) for charT of either char or wchar_t.
+[Sydney: To a large extent this is a nonproblem. As long as +you're only trafficking in char and wchar_t we're only dealing with a +stable character set, so you don't really need either 'widen' or +'narrow': can just use literals. Finally, it's not even clear whether +widen-vs-narrow is the right question; arguably we should be using +codecvt instead.]
+ +Proposed resolution:
+Change stage 2 so that implementations are permitted to use either +technique to perform the comparison:
-
- -- undefined behavior.
-- illegal and must be rejected.
-- legal and must be accepted.
+- call widen on the atoms and compare (either by using + operator== or char_traits<charT>::eq) the input with + the widened atoms, or
+- call narrow on the input and compare the narrow input + with the atoms
+- do (1) or (2) only if charT is not char or wchar_t, + respectively; i.e., avoid calling widen or narrow + if it the source and destination types are the same
My preference is listed in the order presented.
- -There are still other techniques for implementing the requirements of -paragraphs 9-11, namely the "restricted template technique" (e.g. -enable_if). This technique is the most compact and easy way of coding -the requirements, and has the behavior of #2 (rejects the above -expression). -
- +
+461. time_get hard or impossible to implement
Section: 22.2.5.1.2 [lib.locale.time.get.virtuals] Status: Ready Submitter: Bill Plauger Date: 23 Mar 2004
-Choosing 1 would allow all implementation techniques I'm aware of. -Choosing 2 would allow only solution 'A' and the enable_if technique. -Choosing 3 would allow only solution 'B'. +Template time_get currently contains difficult, if not impossible, +requirements for do_date_order, do_get_time, and do_get_date. All require +the implementation to scan a field generated by the %x or %X conversion +specifier in strftime. Yes, do_date_order can always return no_order, but +that doesn't help the other functions. The problem is that %x can be +nearly anything, and it can vary widely with locales. It's horribly +onerous to have to parse "third sunday after Michaelmas in the year of +our Lord two thousand and three," but that's what we currently ask of +do_get_date. More practically, it leads some people to think that if +%x produces 10.2.04, we should know to look for dots as separators. Still +not easy.
-Possible wording for a future standard if we wanted to actively reject -the expression above would be to change "static_cast" in paragraphs -9-11 to "implicit_cast" where that is defined by: +Note that this is the opposite effect from the intent stated in the +footnote earlier in this subclause:
-+template <class T, class U> -inline -T implicit_cast(const U& u) -{ - return u; -} -+"In other words, user confirmation is required for reliable parsing of +user-entered dates and times, but machine-generated formats can be +parsed reliably. This allows parsers to be aggressive about interpreting +user variations on standard formats."+We should give both implementers and users an easier and more reliable +alternative: provide a (short) list of alternative delimiters and say +what the default date order is for no_order. For backward compatibility, +and maximum latitude, we can permit an implementation to parse whatever +%x or %X generates, but we shouldn't require it. +
Proposed resolution:
-Replace 23.1.1 [lib.sequence.reqmts] paragraphs 9 - 11 with: - -For every sequence defined in this clause and in clause lib.strings:
- -
If the constructor
-template <class InputIterator> - X(InputIterator f, InputIterator l, - const allocator_type& a = allocator_type()) --
is called with a type InputIterator that does not qualify as - an input iterator, then the constructor will behave as if the - overloaded constructor:
-X(size_type, const value_type& = value_type(), - const allocator_type& = allocator_type()) --
were called instead, with the arguments static_cast<size_type>(f), l and a, respectively.
-If the member functions of the forms:
-template <class InputIterator> // such as insert() - rt fx1(iterator p, InputIterator f, InputIterator l); - - template <class InputIterator> // such as append(), assign() - rt fx2(InputIterator f, InputIterator l); - - template <class InputIterator> // such as replace() - rt fx3(iterator i1, iterator i2, InputIterator f, InputIterator l); --
are called with a type InputIterator that does not qualify as - an input iterator, then these functions will behave as if the - overloaded member functions:
-rt fx1(iterator, size_type, const value_type&); - - rt fx2(size_type, const value_type&); - - rt fx3(iterator, iterator, size_type, const value_type&); --
were called instead, with the same arguments.
-In the previous paragraph the alternative binding will fail if f -is not implicitly convertible to X::size_type or if l is not implicitly -convertible to X::value_type.
+In the description:
+iter_type do_get_time(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; +
-The extent to which an implementation determines that a type cannot be -an input iterator is unspecified, except that as a minimum integral -types shall not qualify as input iterators. +2 Effects: Reads characters starting at suntil it has extracted those +struct tm members, and remaining format characters, used by +time_put<>::put to produce the format specified by 'X', or until it +encounters an error or end of sequence.
+change: 'X'
+to: "%H:%M:%S"
-[ -Kona: agreed that the current standard requires v('a', 'b') -to be accepted, and also agreed that this is surprising behavior. The -LWG considered several options, including something like -implicit_cast, which doesn't appear to be quite what we want. We -considered Howards three options: allow acceptance or rejection, -require rejection as a compile time error, and require acceptance. By -straw poll (1-6-1), we chose to require a compile time error. -Post-Kona: Howard provided wording. -]
-[ -Sydney: The LWG agreed with this general direction, but there was some -discomfort with the wording in the original proposed resolution. -Howard submitted new wording, and we will review this again in -Redmond. -]
+Change
+iter_type do_get_date(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; --[Redmond: one very small change in wording: the first argument - is cast to size_t. This fixes the problem of something like - vector<vector<int> >(5, 5), where int is not - implicitly convertible to the value type.]
+4 Effects: Reads characters starting at s until it has extracted those +struct tm members, and remaining format characters, used by +time_put<>::put to produce the format specified by 'x', or until it +encounters an error. +
Rationale:
-The proposed resolution fixes:
+to
+iter_type do_get_date(iter_type s, iter_type end, ios_base& str, + ios_base::iostate& err, tm* t) const; -vector<int> v(10, 1); -+4 Effects: Reads characters starting at s until it has extracted those +struct tm members, and remaining format characters, used by +time_put<>::put to produce one of the following formats, or until it +encounters an error. The format depends on the value returned by +date_order() as follows: -
-since as integral types 10 and 1 must be disqualified as input -iterators and therefore the (size,value) constructor is called (as -if).
+ date_order() format -The proposed resolution breaks:
+ no_order "%m/%d/%y" + dmy "%d/%m/%y" + mdy "%m/%d/%y" + ymd "%y/%m/%d" + ydm "%y/%d/%m" -vector<vector<T> > v(10, 1); -+An implementation may also accept additional implementation-defined formats. + -
-because the integral type 1 is not *implicitly* convertible to -vector<T>. The wording above requires a diagnostic.
+[Redmond: agreed that this is a real problem. The solution is + probably to match C99's parsing rules. Bill provided wording. +]
+Section: 3.6.3 [basic.start.term], 18.3 [lib.support.start.term] Status: Open Submitter: Bill Plauger Date: 23 Mar 2004
-The proposed resolution leaves the behavior of the following code -unspecified. +3.6.3 Termination spells out in detail the interleaving of static +destructor calls and calls to functions registered with atexit. To +match this behavior requires intimate cooperation between the code +that calls destructors and the exit/atexit machinery. The former +is tied tightly to the compiler; the latter is a primitive mechanism +inherited from C that traditionally has nothing to do with static +construction and destruction. The benefits of intermixing destructor +calls with atexit handler calls is questionable at best, and very +difficult to get right, particularly when mixing third-party C++ +libraries with different third-party C++ compilers and C libraries +supplied by still other parties.
-struct A - { - operator int () const {return 10;} - }; - - struct B - { - B(A) {} - }; +++I believe the right thing to do is defer all static destruction +until after all atexit handlers are called. This is a change in +behavior, but one that is likely visible only to perverse test +suites. At the very least, we should permit deferred destruction +even if we don't require it. +
+Proposed resolution:
- vector<B> v(A(), A()); -
[If this is to be changed, it should probably be changed by CWG. + At this point, however, the LWG is leaning toward NAD. Implementing + what the standard says is hard work, but it's not impossible and + most vendors went through that pain years ago. Changing this + behavior would be a user-visible change, and would break at least + one real application.]
-The implementation may or may not detect that A is not an input -iterator and employee the (size,value) constructor. Note though that -in the above example if the B(A) constructor is qualified explicit, -then the implementation must reject the constructor as A is no longer -implicitly convertible to B.
Section: 27.8.1 [lib.fstreams] Status: Ready Submitter: Vincent Leloup Date: 20 Nov 2003
+Section: 20.4.5 [lib.auto.ptr] Status: Open Submitter: Rani Sharoni Date: 7 Dec 2003
+-27.8.1.7 [lib.ifstream.members] p1, 27.8.1.10 [lib.ofstream.members] p1, 27.8.1.13 [lib.fstream.members] p1 seems have same problem as exposed in LWG issue -252. +TC1 CWG DR #84 effectively made the template<class Y> operator auto_ptr<Y>() +member of auto_ptr (20.4.5.3/4) obsolete.
-Proposed resolution:
- -[Sydney: Genuine defect. 27.8.1.13 needs a cast to cast away - constness. The other two places are stylistic: we could change the - C-style casts to const_cast. Post-Sydney: Howard provided wording. -]
- -Change 27.8.1.7/1 from:
-- Returns: (basic_filebuf<charT,traits>*)&sb. -- -
to:
-- Returns: const_cast<basic_filebuf<charT,traits>*>(&sb). --
Change 27.8.1.10/1 from:
-- Returns: (basic_filebuf<charT,traits>*)&sb. -+
+The sole purpose of this obsolete conversion member is to enable copy +initialization base from r-value derived (or any convertible types like +cv-types) case: +
+#include <memory> +using std::auto_ptr; --to:
-- Returns: const_cast<basic_filebuf<charT,traits>*>(&sb). -+struct B {}; +struct D : B {}; -Change 27.8.1.13/1 from:
-- Returns: &sb. -+auto_ptr<D> source(); +int sink(auto_ptr<B>); +int x1 = sink( source() ); // #1 EDG - no suitable copy constructor +
to:
-- Returns: const_cast<basic_filebuf<charT,traits>*>(&sb). -+
+The excellent analysis of conversion operations that was given in the final +auto_ptr proposal +(http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/1997/N1128.pdf) +explicitly specifies this case analysis (case 4). DR #84 makes the analysis +wrong and actually comes to forbid the loophole that was exploited by the +auto_ptr designers. +
++I didn't encounter any compliant compiler (e.g. EDG, GCC, BCC and VC) that +ever allowed this case. This is probably because it requires 3 user defined +conversions and in fact current compilers conform to DR #84. +
++I was surprised to discover that the obsolete conversion member actually has +negative impact of the copy initialization base from l-value derived +case:
+auto_ptr<D> dp; +int x2 = sink(dp); // #2 EDG - more than one user-defined conversion applies +-
Section: 24.3.1 [lib.iterator.traits] Status: Ready Submitter: Dave Abrahams Date: 9 Dec 2003
-The standard places no restrictions at all on the reference type -of input, output, or forward iterators (for forward iterators it -only specifies that *x must be value_type& and doesn't mention -the reference type). Bidirectional iterators' reference type is -restricted only by implication, since the base iterator's -reference type is used as the return type of reverse_iterator's -operator*, which must be T& in order to be a conforming forward -iterator. +I'm sure that the original intention was allowing this initialization using +the template<class Y> auto_ptr(auto_ptr<Y>& a) constructor (20.4.5.1/4) but +since in this copy initialization it's merely user defined conversion (UDC) +and the obsolete conversion member is UDC with the same rank (for the early +overloading stage) there is an ambiguity between them.
-Here's what I think we ought to be able to expect from an input -or forward iterator's reference type R, where a is an iterator -and V is its value_type +Removing the obsolete member will have impact on code that explicitly +invokes it:
+int y = sink(source().operator auto_ptr<B>()); +-
+IMHO no one ever wrote such awkward code and the reasonable workaround for +#1 is: +
+int y = sink( auto_ptr<B>(source()) ); +-
+I was even more surprised to find out that after removing the obsolete +conversion member the initialization was still ill-formed: +int x3 = sink(dp); // #3 EDG - no suitable copy constructor +
-A mutable forward iterator ought to satisfy, for x of type V:
-+This copy initialization semantically requires copy constructor which means +that both template conversion constructor and the auto_ptr_ref conversion +member (20.4.5.3/3) are required which is what was explicitly forbidden in +DR #84. This is a bit amusing case in which removing ambiguity results with +no candidates. +
-I think these requirements capture existing container iterators -(including vector<bool>'s), but render istream_iterator invalid; -its reference type would have to be changed to a constant -reference. +I also found exception safety issue with auto_ptr related to auto_ptr_ref:
+int f(auto_ptr<B>, std::string); +auto_ptr<B> source2(); +// string constructor throws while auto_ptr_ref +// "holds" the pointer +int x4 = f(source2(), "xyz"); // #4 +
-(Jeremy Siek) During the discussion in Sydney, it was felt that a -simpler long term solution for this was needed. The solution proposed -was to require reference to be the same type as *a -and pointer to be the same type as a->. Most -iterators in the Standard Library already meet this requirement. Some -iterators are output iterators, and do not need to meet the -requirement, and others are only specified through the general -iterator requirements (which will change with this resolution). The -sole case where there is an explicit definition of the reference type -that will need to change is istreambuf_iterator which returns -charT from operator* but has a reference type of -charT&. We propose changing the reference type of -istreambuf_iterator to charT. +The theoretic execution sequence that will cause a leak:
+The other option for resolving the issue with pointer, - mentioned in the note below, is to remove pointer - altogether. I prefer placing requirements on pointer to - removing it for two reasons. First, pointer will become - useful for implementing iterator adaptors and in particular, - reverse_iterator will become more well defined. Second, - removing pointer is a rather drastic and publicly-visible - action to take.
++According to 20.4.5.3/3 and 20.4.5/2 the auto_ptr_ref conversion member +returns auto_ptr_ref<Y> that holds *this and this is another defect since +the type of *this is auto_ptr<X> where X might be different from Y. Several +library vendors (e.g. SGI) implement auto_ptr_ref<Y> with Y* as member which +is much more reasonable. Other vendor implemented auto_ptr_ref as +defectively required and it results with awkward and catastrophic code: +int oops = sink(auto_ptr<B>(source())); // warning recursive on all control +paths +
-The proposed resolution technically enlarges the requirements for -iterators, which means there are existing iterators (such as -istreambuf_iterator, and potentially some programmer-defined -iterators) that will no longer meet the requirements. Will this break -existing code? The scenario in which it would is if an algorithm -implementation (say in the Standard Library) is changed to rely on -iterator_traits::reference, and then is used with one of the -iterators that do not have an appropriately defined -iterator_traits::reference. +
+Dave Abrahams noticed that there is no specification saying that +auto_ptr_ref copy constructor can't throw.
++My proposal comes to solve all the above issues and significantly simplify +auto_ptr implementation. One of the fundamental requirements from auto_ptr +is that it can be constructed in an intuitive manner (i.e. like ordinary +pointers) but with strict ownership semantics which yield that source +auto_ptr in initialization must be non-const. My idea is to add additional +constructor template with sole propose to generate ill-formed, diagnostic +required, instance for const auto_ptr arguments during instantiation of +declaration. This special constructor will not be instantiated for other +types which is achievable using 14.8.2/2 (SFINAE). Having this constructor +in hand makes the constructor template<class Y> auto_ptr(auto_ptr<Y> const&) +legitimate since the actual argument can't be const yet non const r-value +are acceptable. +
-The proposed resolution makes one other subtle change. Previously, -it was required that output iterators have a difference_type -and value_type of void, which means that a forward -iterator could not be an output iterator. This is clearly a mistake, -so I've changed the wording to say that those types may be -void. +
+This implementation technique makes the "private auxiliary class" +auto_ptr_ref obsolete and I found out that modern C++ compilers (e.g. EDG, +GCC and VC) consume the new implementation as expected and allow all +intuitive initialization and assignment cases while rejecting illegal cases +that involve const auto_ptr arguments.
-Proposed resolution:
+The proposed auto_ptr interface:
-In 24.3.1 [lib.iterator.traits], after:
+namespace std { + template<class X> class auto_ptr { + public: + typedef X element_type; --be defined as the iterator's difference type, value type and iterator -category, respectively. -+ // 20.4.5.1 construct/copy/destroy: + explicit auto_ptr(X* p=0) throw(); + auto_ptr(auto_ptr&) throw(); + template<class Y> auto_ptr(auto_ptr<Y> const&) throw(); + auto_ptr& operator=(auto_ptr&) throw(); + template<class Y> auto_ptr& operator=(auto_ptr<Y>) throw(); + ~auto_ptr() throw(); -add
+ // 20.4.5.2 members: + X& operator*() const throw(); + X* operator->() const throw(); + X* get() const throw(); + X* release() throw(); + void reset(X* p=0) throw(); --In addition, the types --iterator_traits<Iterator>::reference -iterator_traits<Iterator>::pointer + private: + template<class U> + auto_ptr(U& rhs, typename +unspecified_error_on_const_auto_ptr<U>::type = 0); + }; +}-must be defined as the iterator's reference and pointer types, that -is, the same type as the type of *a and a->, -respectively. -In 24.3.1 [lib.iterator.traits], change:
++One compliant technique to implement the unspecified_error_on_const_auto_ptr +helper class is using additional private auto_ptr member class template like +the following: +
+template<typename T> struct unspecified_error_on_const_auto_ptr; --In the case of an output iterator, the types --iterator_traits<Iterator>::difference_type -iterator_traits<Iterator>::value_type +template<typename T> +struct unspecified_error_on_const_auto_ptr<auto_ptr<T> const> +{ typedef typename auto_ptr<T>::const_auto_ptr_is_not_allowed type; };-are both defined as void. -to:
--In the case of an output iterator, the types -+iterator_traits<Iterator>::difference_type -iterator_traits<Iterator>::value_type -iterator_traits<Iterator>::reference -iterator_traits<Iterator>::pointer --may be defined as void. -+There are other techniques to implement this helper class that might work +better for different compliers (i.e. better diagnostics) and therefore I +suggest defining its semantic behavior without mandating any specific +implementation. IMO, and I didn't found any compiler that thinks otherwise, +14.7.1/5 doesn't theoretically defeat the suggested technique but I suggest +verifying this with core language experts. +
-In 24.5.3 [lib.istreambuf.iterator], change:
---typename traits::off_type, charT*, charT&> --to:
--+typename traits::off_type, charT*, charT> --Further changes in standard text:
+Remove section 20.4.5.3
-[ -Redmond: there was concern in Sydney that this might not be the only place -where things were underspecified and needed to be changed. Jeremy -reviewed iterators in the standard and confirmed that nothing else -needed to be changed. -]
+Change 20.4.5/2 to read something like: +Initializing auto_ptr<X> from const auto_ptr<Y> will result with unspecified +ill-formed declaration that will require unspecified diagnostic.
-
-446. Iterator equality between different containers
Section: 24.1 [lib.iterator.requirements], 23.1 [lib.container.requirements] Status: Open Submitter: Andy Koenig Date: 16 Dec 2003
+Change 20.4.5.1/4,5,6 to read:
+ +template<class Y> auto_ptr(auto_ptr<Y> const& a) throw();+4 Requires: Y* can be implicitly converted to X*.
+5 Effects: Calls const_cast<auto_ptr<Y>&>(a).release().
+6 Postconditions: *this holds the pointer returned from a.release().
+ +Change 20.4.5.1/10
+template<class Y> auto_ptr& operator=(auto_ptr<Y> a) throw(); +-What requirements does the standard place on equality comparisons between -iterators that refer to elements of different containers. For example, if -v1 and v2 are empty vectors, is v1.end() == v2.end() allowed to yield true? -Is it allowed to throw an exception? +10 Requires: Y* can be implicitly converted to X*. The expression delete +get() is well formed.
--The standard appears to be silent on both questions. -
-Proposed resolution:
- -[Sydney: The intention is that comparing two iterators from -different containers is undefined, but it's not clear if we say that, -or even whether it's something we should be saying in clause 23 or in -clause 24. Intuitively we might want to say that equality is defined -only if one iterator is reachable from another, but figuring out how -to say it in any sensible way is a bit tricky: reachability is defined -in terms of equality, so we can't also define equality in terms of -reachability. -]
- -
-453. basic_stringbuf::seekoff need not always fail for an empty stream
Section: 27.7.1.3 [lib.stringbuf.virtuals] Status: Ready Submitter: Bill Plauger Date: 30 Jan 2004
-pos_type basic_stringbuf::seekoff(off_type, ios_base::seekdir, - ios_base::openmode); ---is obliged to fail if nothing has been inserted into the stream. This -is unnecessary and undesirable. It should be permissible to seek to -an effective offset of zero.
- -[ - Sydney: Agreed that this is an annoying problem: seeking to zero should be - legal. Bill will provide wording. -]
- -Proposed resolution:
-Change the sentence from:
--For a sequence to be positioned, if its next pointer (either -gptr() or pptr()) is a null pointer, the positioning operation -fails. -- -to:
- --For a sequence to be positioned, if its next pointer (either -gptr() or pptr()) is a null pointer and the new offset newoff -is nonzero, the positioning operation fails. --
-454. basic_filebuf::open should accept wchar_t names
Section: 27.8.1.3 [lib.filebuf.members] Status: Ready Submitter: Bill Plauger Date: 30 Jan 2004
-basic_filebuf *basic_filebuf::open(const char *, ios_base::open_mode); -- -should be supplemented with the overload:
- -basic_filebuf *basic_filebuf::open(const wchar_t *, ios_base::open_mode); -- --Depending on the operating system, one of these forms is fundamental and -the other requires an implementation-defined mapping to determine the -actual filename. -
- -[Sydney: Yes, we want to allow wchar_t filenames. Bill will - provide wording.]
- -Proposed resolution:
- -Change from:
--- -basic_filebuf<charT,traits>* open( - const char* s, - ios_base::openmode mode ); -- --Effects: If is_open() != false, returns a null pointer. -Otherwise, initializes the filebuf as required. It then -opens a file, if possible, whose name is the NTBS s ("as if" -by calling std::fopen(s,modstr)).
-to:
- --- -basic_filebuf<charT,traits>* open( - const char* s, - ios_base::openmode mode ); - -basic_filebuf<charT,traits>* open( - const wchar_t* ws, - ios_base::openmode mode ); -- --Effects: If is_open() != false, returns a null pointer. -Otherwise, initializes the filebuf as required. It then -opens a file, if possible, whose name is the NTBS s ("as if" -by calling std::fopen(s,modstr)). -For the second signature, the NTBS s is determined from the -WCBS ws in an implementation-defined manner. -
- --(NOTE: For a system that "naturally" represents a filename -as a WCBS, the NTBS s in the first signature may instead -be mapped to a WCBS; if so, it follows the same mapping -rules as the first argument to open.) -
-Rationale:
--Slightly controversial, but by a 7-1 straw poll the LWG agreed to move -this to Ready. The controversy was because the mapping between wide -names and files in a filesystem is implementation defined. The -counterargument, which most but not all LWG members accepted, is that -the mapping between narrow files names and files is also -implemenation defined.
-
-455. cerr::tie() and wcerr::tie() are overspecified
Section: 27.3 [lib.iostream.objects] Status: Ready Submitter: Bill Plauger Date: 30 Jan 2004
--Both cerr::tie() and wcerr::tie() are obliged to be null at program -startup. This is overspecification and overkill. It is both traditional -and useful to tie cerr to cout, to ensure that standard output is drained -whenever an error message is written. This behavior should at least be -permitted if not required. Same for wcerr::tie(). -
-Proposed resolution:
- -Add to the description of cerr:
--After the object cerr is initialized, cerr.tie() returns &cout. -Its state is otherwise the same as required for basic_ios<char>::init -(lib.basic.ios.cons). -- -Add to the description of wcerr:
- --After the object wcerr is initialized, wcerr.tie() returns &wcout. -Its state is otherwise the same as required for basic_ios<wchar_t>::init -(lib.basic.ios.cons). -- -[Sydney: straw poll (3-1): we should require, not just - permit, cout and cerr to be tied on startup. Pre-Redmond: Bill will - provide wording.]
-
-456. Traditional C header files are overspecified
Section: 17.4.1.2 [lib.headers] Status: Open Submitter: Bill Plauger Date: 30 Jan 2004
- -The C++ Standard effectively requires that the traditional C headers -(of the form <xxx.h>) be defined in terms of the newer C++ -headers (of the form <cxxx>). Clauses 17.4.1.2/4 and D.5 combine -to require that:
- -
-The rules were left in this form despited repeated and heated objections -from several compiler vendors. The C headers are often beyond the direct -control of C++ implementors. In some organizations, it's all they can do -to get a few #ifdef __cplusplus tests added. Third-party library vendors -can perhaps wrap the C headers. But neither of these approaches supports -the drastic restructuring required by the C++ Standard. As a result, it is -still widespread practice to ignore this conformance requirement, nearly -seven years after the committee last debated this topic. Instead, what is -often implemented is: -
- --The practical benefit for implementors with the second approach is that -they can use existing C library headers, as they are pretty much obliged -to do. The practical cost for programmers facing a mix of implementations -is that they have to assume weaker rules:
- --There also exists the possibility of subtle differences due to -Koenig lookup, but there are so few non-builtin types defined in the C -headers that I've yet to see an example of any real problems in this -area. -
- --It is worth observing that the rate at which programmers fall afoul of -these differences has remained small, at least as measured by newsgroup -postings and our own bug reports. (By an overwhelming margin, the -commonest problem is still that programmers include <string> and can't -understand why the typename string isn't defined -- this a decade after -the committee invented namespace std, nominally for the benefit of all -programmers.) -
- --We should accept the fact that we made a serious mistake and rectify it, -however belatedly, by explicitly allowing either of the two schemes for -declaring C names in headers. -
- -[Sydney: This issue has been debated many times, and will - certainly have to be discussed in full committee before any action - can be taken. However, the preliminary sentiment of the LWG was in - favor of the change. (6 yes, 0 no, 2 abstain) Robert Klarer - suggests that we might also want to undeprecate the - C-style .h headers.]
- -Proposed resolution:
-Section: 23.3.5.1 [lib.bitset.cons] Status: Ready Submitter: Dag Henriksson Date: 30 Jan 2004
--The constructor from unsigned long says it initializes "the first M -bit positions to the corresponding bit values in val. M is the smaller -of N and the value CHAR_BIT * sizeof(unsigned long)." -
- --Object-representation vs. value-representation strikes again. CHAR_BIT * -sizeof (unsigned long) does not give us the number of bits an unsigned long -uses to hold the value. Thus, the first M bit position above is not -guaranteed to have any corresponding bit values in val. -
-Proposed resolution:
-In 23.3.5.1 [lib.bitset.cons] paragraph 2, change "M is the smaller of - N and the value CHAR_BIT * sizeof (unsigned long). (249)" to - "M is the smaller of N and the number of bits in - the value representation (section 3.9 [basic.types]) of unsigned - long." -
-Section: 24.1.5 [lib.random.access.iterators] Status: Open Submitter: Daniel Frey Date: 27 Feb 2004
--In 24.1.5 [lib.random.access.iterators], table 76 the operational -semantics for the expression "r -= n" are defined as "return r += -n". -This means, that the expression -n must be valid, which is not the case -for unsigned types. -
- -[ -Sydney: Possibly not a real problem, since difference type is required -to be a signed integer type. However, the wording in the standard may -be less clear than we would like. -]
- -Proposed resolution:
--To remove this limitation, I suggest to change the -operational semantics for this column to: -
-
- { Distance m = n;
- if (m >= 0)
- while (m--) --r;
- else
- while (m++) ++r;
- return r; }
-
-
-Section: 22.2.2.1.2 [lib.facet.num.get.virtuals] Status: Open Submitter: Martin Sebor Date: 16 Mar 2004
-When parsing strings of wide-character digits, the standard - requires the library to widen narrow-character "atoms" and compare - the widened atoms against the characters that are being parsed. - Simply narrowing the wide characters would be far simpler, and - probably more efficient. The two choices are equivalent except in - convoluted test cases, and many implementations already ignore the - standard and use narrow instead of widen.
- --First, I disagree that using narrow() instead of widen() would -necessarily have unfortunate performance implications. A possible -implementation of narrow() that allows num_get to be implemented -in a much simpler and arguably comparably efficient way as calling -widen() allows, i.e. without making a virtual call to do_narrow every -time, is as follows: -
- -inline char ctype<wchar_t>::narrow (wchar_t wc, char dflt) const - { - const unsigned wi = unsigned (wc); - - if (wi > UCHAR_MAX) - return typeid (*this) == typeid (ctype<wchar_t>) ? - dflt : do_narrow (wc, dflt); - - if (narrow_ [wi] < 0) { - const char nc = do_narrow (wc, dflt); - if (nc == dflt) - return dflt; - narrow_ [wi] = nc; - } - - return char (narrow_ [wi]); - } -- -
-Second, I don't think the change proposed in the issue (i.e., to use -narrow() instead of widen() during Stage 2) would be at all -drastic. Existing implementations with the exception of libstdc++ -currently already use narrow() so the impact of the change on programs -would presumably be isolated to just a single implementation. Further, -since narrow() is not required to translate alternate wide digit -representations such as those mentioned in issue 303 to -their narrow equivalents (i.e., the portable source characters '0' -through '9'), the change does not necessarily imply that these -alternate digits would be treated as ordinary digits and accepted as -part of numbers during parsing. In fact, the requirement in 22.2.1.1.2 [lib.locale.ctype.virtuals], p13 forbids narrow() to translate an alternate -digit character, wc, to an ordinary digit in the basic source -character set unless the expression -(ctype<charT>::is(ctype_base::digit, wc) == true) holds. This in -turn is prohibited by the C standard (7.25.2.1.5, 7.25.2.1.5, and -5.2.1, respectively) for charT of either char or wchar_t. -
- -[Sydney: To a large extent this is a nonproblem. As long as -you're only trafficking in char and wchar_t we're only dealing with a -stable character set, so you don't really need either 'widen' or -'narrow': can just use literals. Finally, it's not even clear whether -widen-vs-narrow is the right question; arguably we should be using -codecvt instead.]
- -Proposed resolution:
-Change stage 2 so that implementations are permitted to use either -technique to perform the comparison:
-Section: 27.8.1 [lib.fstreams] Status: Ready Submitter: Ben Hutchings Date: 1 Apr 2004
--The second parameters of the non-default constructor and of the open -member function for basic_fstream, named "mode", are optional -according to the class declaration in 27.8.1.11 [lib.fstream]. The -specifications of these members in 27.8.1.12 [lib.fstream.cons] and -27.8.1.13 lib.fstream.members] disagree with this, though the -constructor declaration has the "explicit" function-specifier implying -that it is intended to be callable with one argument. -
-Proposed resolution:
-In 27.8.1.12 [lib.fstream.cons], change
-explicit basic_fstream(const char* s, ios_base::openmode mode); --
to
-explicit basic_fstream(const char* s, - ios_base::openmode mode = ios_base::in|ios_base::out); --
In 27.8.1.13 [lib.fstream.members], change
-void open(const char*s, ios_base::openmode mode); --
to
- void open(const char*s, - ios_base::openmode mode = ios_base::in|ios_base::out); -Section: 22.2.5.1.2 [lib.locale.time.get.virtuals] Status: Review Submitter: Bill Plauger Date: 23 Mar 2004
--Template time_get currently contains difficult, if not impossible, -requirements for do_date_order, do_get_time, and do_get_date. All require -the implementation to scan a field generated by the %x or %X conversion -specifier in strftime. Yes, do_date_order can always return no_order, but -that doesn't help the other functions. The problem is that %x can be -nearly anything, and it can vary widely with locales. It's horribly -onerous to have to parse "third sunday after Michaelmas in the year of -our Lord two thousand and three," but that's what we currently ask of -do_get_date. More practically, it leads some people to think that if -%x produces 10.2.04, we should know to look for dots as separators. Still -not easy. -
- --Note that this is the opposite effect from the intent stated in the -footnote earlier in this subclause: -
- --"In other words, user confirmation is required for reliable parsing of -user-entered dates and times, but machine-generated formats can be -parsed reliably. This allows parsers to be aggressive about interpreting -user variations on standard formats." -- -
-We should give both implementers and users an easier and more reliable -alternative: provide a (short) list of alternative delimiters and say -what the default date order is for no_order. For backward compatibility, -and maximum latitude, we can permit an implementation to parse whatever -%x or %X generates, but we shouldn't require it. -
-Proposed resolution:
- -In the description:
-iter_type do_get_time(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; -- -
-2 Effects: Reads characters starting at suntil it has extracted those -struct tm members, and remaining format characters, used by -time_put<>::put to produce the format specified by 'X', or until it -encounters an error or end of sequence. -
- -change: 'X'
- -to: "%H:%M:%S"
- - -In the description:
-iter_type do_get_date(iter_type s, iter_type end, ios_base& str, - ios_base::iostate& err, tm* t) const; --
-4 Effects: Reads characters starting at suntil it has extracted those -struct tm members, and remaining format characters, used by -time_put<>::put to produce the format specified by 'x', or until it -encounters an error. -
- --change: used by time_put<>::put to produce the format -specified by 'x', or until it encounters an error. -
- -to: used by time_put<>:: put to produce one of the -following formats, or until it encounters an error. The format depends -on the value returned by date_order() as follows: -
-date_order() format - - no_order "%m/%d/%y" - dmy "%d/%m/%y" - mdy "%m/%d/%y" - ymd "%y/%m/%d" - ydm "%y/%d/%m" -- -
[Redmond: agreed that this is a real problem. The solution is - probably to match C99's parsing rules. Bill provided wording. -]
- -Section: 3.6.3 [basic.start.term], 18.3 [lib.support.start.term] Status: Open Submitter: Bill Plauger Date: 23 Mar 2004
--3.6.3 Termination spells out in detail the interleaving of static -destructor calls and calls to functions registered with atexit. To -match this behavior requires intimate cooperation between the code -that calls destructors and the exit/atexit machinery. The former -is tied tightly to the compiler; the latter is a primitive mechanism -inherited from C that traditionally has nothing to do with static -construction and destruction. The benefits of intermixing destructor -calls with atexit handler calls is questionable at best, and very -difficult to get right, particularly when mixing third-party C++ -libraries with different third-party C++ compilers and C libraries -supplied by still other parties. -
- --I believe the right thing to do is defer all static destruction -until after all atexit handlers are called. This is a change in -behavior, but one that is likely visible only to perverse test -suites. At the very least, we should permit deferred destruction -even if we don't require it. -
-Proposed resolution:
- -[If this is to be changed, it should probably be changed by CWG. - At this point, however, the LWG is leaning toward NAD. Implementing - what the standard says is hard work, but it's not impossible and - most vendors went through that pain years ago. Changing this - behavior would be a user-visible change, and would break at least - one real application.]
- --
-Section: 20.4.5 [lib.auto.ptr] Status: Open Submitter: Rani Sharoni Date: 7 Dec 2003
- --TC1 CWG DR #84 effectively made the template<class Y> operator auto_ptr<Y>() -member of auto_ptr (20.4.5.3/4) obsolete. -
- --The sole purpose of this obsolete conversion member is to enable copy -initialization base from r-value derived (or any convertible types like -cv-types) case: -
-#include <memory> -using std::auto_ptr; - -struct B {}; -struct D : B {}; - -auto_ptr<D> source(); -int sink(auto_ptr<B>); -int x1 = sink( source() ); // #1 EDG - no suitable copy constructor -- -
-The excellent analysis of conversion operations that was given in the final -auto_ptr proposal -(http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/1997/N1128.pdf) -explicitly specifies this case analysis (case 4). DR #84 makes the analysis -wrong and actually comes to forbid the loophole that was exploited by the -auto_ptr designers. -
- --I didn't encounter any compliant compiler (e.g. EDG, GCC, BCC and VC) that -ever allowed this case. This is probably because it requires 3 user defined -conversions and in fact current compilers conform to DR #84. -
- --I was surprised to discover that the obsolete conversion member actually has -negative impact of the copy initialization base from l-value derived -case:
-auto_ptr<D> dp; -int x2 = sink(dp); // #2 EDG - more than one user-defined conversion applies -- -
-I'm sure that the original intention was allowing this initialization using -the template<class Y> auto_ptr(auto_ptr<Y>& a) constructor (20.4.5.1/4) but -since in this copy initialization it's merely user defined conversion (UDC) -and the obsolete conversion member is UDC with the same rank (for the early -overloading stage) there is an ambiguity between them. -
- --Removing the obsolete member will have impact on code that explicitly -invokes it: -
-int y = sink(source().operator auto_ptr<B>()); -- -
-IMHO no one ever wrote such awkward code and the reasonable workaround for -#1 is: -
-int y = sink( auto_ptr<B>(source()) ); -- -
-I was even more surprised to find out that after removing the obsolete -conversion member the initialization was still ill-formed: -int x3 = sink(dp); // #3 EDG - no suitable copy constructor -
- --This copy initialization semantically requires copy constructor which means -that both template conversion constructor and the auto_ptr_ref conversion -member (20.4.5.3/3) are required which is what was explicitly forbidden in -DR #84. This is a bit amusing case in which removing ambiguity results with -no candidates. -
- --I also found exception safety issue with auto_ptr related to auto_ptr_ref: -
-int f(auto_ptr<B>, std::string); -auto_ptr<B> source2(); - -// string constructor throws while auto_ptr_ref -// "holds" the pointer -int x4 = f(source2(), "xyz"); // #4 -- -
-The theoretic execution sequence that will cause a leak: -
--According to 20.4.5.3/3 and 20.4.5/2 the auto_ptr_ref conversion member -returns auto_ptr_ref<Y> that holds *this and this is another defect since -the type of *this is auto_ptr<X> where X might be different from Y. Several -library vendors (e.g. SGI) implement auto_ptr_ref<Y> with Y* as member which -is much more reasonable. Other vendor implemented auto_ptr_ref as -defectively required and it results with awkward and catastrophic code: -int oops = sink(auto_ptr<B>(source())); // warning recursive on all control -paths -
- --Dave Abrahams noticed that there is no specification saying that -auto_ptr_ref copy constructor can't throw. -
- --My proposal comes to solve all the above issues and significantly simplify -auto_ptr implementation. One of the fundamental requirements from auto_ptr -is that it can be constructed in an intuitive manner (i.e. like ordinary -pointers) but with strict ownership semantics which yield that source -auto_ptr in initialization must be non-const. My idea is to add additional -constructor template with sole propose to generate ill-formed, diagnostic -required, instance for const auto_ptr arguments during instantiation of -declaration. This special constructor will not be instantiated for other -types which is achievable using 14.8.2/2 (SFINAE). Having this constructor -in hand makes the constructor template<class Y> auto_ptr(auto_ptr<Y> const&) -legitimate since the actual argument can't be const yet non const r-value -are acceptable. -
- --This implementation technique makes the "private auxiliary class" -auto_ptr_ref obsolete and I found out that modern C++ compilers (e.g. EDG, -GCC and VC) consume the new implementation as expected and allow all -intuitive initialization and assignment cases while rejecting illegal cases -that involve const auto_ptr arguments. -
- -The proposed auto_ptr interface:
- -namespace std { - template<class X> class auto_ptr { - public: - typedef X element_type; - - // 20.4.5.1 construct/copy/destroy: - explicit auto_ptr(X* p=0) throw(); - auto_ptr(auto_ptr&) throw(); - template<class Y> auto_ptr(auto_ptr<Y> const&) throw(); - auto_ptr& operator=(auto_ptr&) throw(); - template<class Y> auto_ptr& operator=(auto_ptr<Y>) throw(); - ~auto_ptr() throw(); - - // 20.4.5.2 members: - X& operator*() const throw(); - X* operator->() const throw(); - X* get() const throw(); - X* release() throw(); - void reset(X* p=0) throw(); - - private: - template<class U> - auto_ptr(U& rhs, typename -unspecified_error_on_const_auto_ptr<U>::type = 0); - }; -} -- -
-One compliant technique to implement the unspecified_error_on_const_auto_ptr -helper class is using additional private auto_ptr member class template like -the following: -
-template<typename T> struct unspecified_error_on_const_auto_ptr; - -template<typename T> -struct unspecified_error_on_const_auto_ptr<auto_ptr<T> const> -{ typedef typename auto_ptr<T>::const_auto_ptr_is_not_allowed type; }; -- -
-There are other techniques to implement this helper class that might work -better for different compliers (i.e. better diagnostics) and therefore I -suggest defining its semantic behavior without mandating any specific -implementation. IMO, and I didn't found any compiler that thinks otherwise, -14.7.1/5 doesn't theoretically defeat the suggested technique but I suggest -verifying this with core language experts. -
- -Further changes in standard text:
-Remove section 20.4.5.3
- -Change 20.4.5/2 to read something like: -Initializing auto_ptr<X> from const auto_ptr<Y> will result with unspecified -ill-formed declaration that will require unspecified diagnostic.
- -Change 20.4.5.1/4,5,6 to read:
- -template<class Y> auto_ptr(auto_ptr<Y> const& a) throw();-
4 Requires: Y* can be implicitly converted to X*.
-5 Effects: Calls const_cast<auto_ptr<Y>&>(a).release().
-6 Postconditions: *this holds the pointer returned from a.release().
- -Change 20.4.5.1/10
-template<class Y> auto_ptr& operator=(auto_ptr<Y> a) throw(); --
-10 Requires: Y* can be implicitly converted to X*. The expression delete -get() is well formed. -
- -LWG TC DR #127 is obsolete.
- --Notice that the copy constructor and copy assignment operator should remain -as before and accept non-const auto_ptr& since they have effect on the form -of the implicitly declared copy constructor and copy assignment operator of -class that contains auto_ptr as member per 12.8/5,10: -
-struct X { - // implicit X(X&) - // implicit X& operator=(X&) - auto_ptr<D> aptr_; -}; -- -
-In most cases this indicates about sloppy programming but preserves the -current auto_ptr behavior. -
- --Dave Abrahams encouraged me to suggest fallback implementation in case that -my suggestion that involves removing of auto_ptr_ref will not be accepted. -In this case removing the obsolete conversion member to auto_ptr<Y> and -20.4.5.3/4,5 is still required in order to eliminate ambiguity in legal -cases. The two constructors that I suggested will co exist with the current -members but will make auto_ptr_ref obsolete in initialization contexts. -auto_ptr_ref will be effective in assignment contexts as suggested in DR -#127 and I can't see any serious exception safety issues in those cases -(although it's possible to synthesize such). auto_ptr_ref<X> semantics will -have to be revised to say that it strictly holds pointer of type X and not -reference to an auto_ptr for the favor of cases in which auto_ptr_ref<Y> is -constructed from auto_ptr<X> in which X is different from Y (i.e. assignment -from r-value derived to base). -
- -Proposed resolution:
-[Redmond: punt for the moment. We haven't decided yet whether we - want to fix auto_ptr for C++-0x, or remove it and replace it with - move_ptr and unique_ptr.]
-Section: 23.2.4 [lib.vector], 23.3.1 [lib.map] Status: Review Submitter: Thorsten Ottosen Date: 12 May 2004
- -To add slightly more convenience to vector<T> and map<Key,T> we should consider to add
-Rationale:
- -Proposed resolution:
-In 23.2.4 [lib.vector], add the following to the vector - synopsis after "element access" and before "modifiers":
-// [lib.vector.data] data access - pointer data(); - const_pointer data() const; -- -
Add a new subsection of 23.2.4 [lib.vector]:
--- -23.2.4.x vector data access
-pointer data(); - const_pointer data() const; --Returns: A pointer such that [data(), data() + size()) is a valid - range that contains the same elements as [begin(), end()).
-Complexity: Constant time.
-Throws: Nothing.
-
In 23.3.1 [lib.map], add the following to the map -synopsis immediately after the line for operator[]:
-T& at(const key_type& x); - const T& at(const key_type& x) const; -- -
Add the following to 23.3.1.2 [lib.map.access]:
--- -T& at(const key_type& x); - const T& at(const key_type& x) const; -- -Returns: A reference to the element whose key is equivalent - to x, if such an element is present in the map.
-Throws: out_of_range if no such element is present.
- -
Rationale:
-Neither of these additions provides any new functionality but the - LWG agreed that they are convenient, especially for novices. The - exception type chosen for at, std::out_of_range, - was chosen to match vector::at.
-Section: 17.4.1.2 [lib.headers] Status: Review Submitter: Steve Clamage Date: 3 Jun 2004
-C header <iso646.h> defines macros for some operators, such as -not_eq for !=.
- -Section 17.4.1.2 [lib.headers] "Headers" says that except as noted in -clauses 18 through 27, the <cname> C++ header contents are the same -as the C header <name.h>. In particular, table 12 lists -<ciso646> as a C++ header.
- -I don't find any other mention of <ciso646>, or any mention of -<iso646.h>, in clauses 17 thorough 27. That implies that the -contents of <ciso646> are the same as C header <iso646.h>.
- -Annex C (informative, not normative) in [diff.header.iso646.h] C.2.2.2 -"Header <iso646.h>" says that the alternative tokens are not -defined as macros in <ciso646>, but does not mention the contents -of <iso646.h>.
- -I don't find any normative text to support C.2.2.2.
- -Proposed resolution:
-Add to section 17.4.1.2 Headers [lib.headers] a new paragraph after - paragraph 6 (the one about functions must be functions):
- --- -Identifiers that are keywords or operators in C++ shall not be defined -as macros in C++ standard library headers. -[Footnote:In particular, including the standard header <iso646.h> -or <ciso646> has no effect.
-
[post-Redmond: Steve provided wording.]
- -Section: 21.3.1 [lib.string.cons] Status: Open Submitter: Daniel Frey Date: 10 Jun 2004
--Today, my colleagues and me wasted a lot of time. After some time, I -found the problem. It could be reduced to the following short example: -
- -#include <string> - int main() { std::string( 0 ); } -- -
The problem is that the tested compilers (GCC 2.95.2, GCC 3.3.1 and -Comeau online) compile the above without errors or warnings! The -programs (at least for the GCC) resulted in a SEGV.
- -I know that the standard explicitly states that the ctor of string -requires a char* which is not zero. STLs could easily detect the above -case with a private ctor for basic_string which takes a single 'int' -argument. This would catch the above code at compile time and would not -ambiguate any other legal ctors.
- -Proposed resolution:
-[Redmond: No great enthusiasm for doing this. If we do, - however, we want to do it for all places that take charT* - pointers, not just the single-argument constructor. The other - question is whether we want to catch this at compile time (in which - case we catch the error of a literal 0, but not an expression whose - value is a null pointer), at run time, or both.]
- -Section: 21.1.3.1 [lib.char.traits.specializations.char] Status: Review Submitter: Martin Sebor Date: 28 Jun 2004
- --Table 37 describes the requirements on Traits::compare() in terms of -those on Traits::lt(). 21.1.3.1, p6 requires char_traits<char>::lt() -to yield the same result as operator<(char, char). -
- --Most, if not all, implementations of char_traits<char>::compare() -call memcmp() for efficiency. However, the C standard requires both -memcmp() and strcmp() to interpret characters under comparison as -unsigned, regardless of the signedness of char. As a result, all -these char_traits implementations fail to meet the requirement -imposed by Table 37 on compare() when char is signed. -
- - -Read email thread starting with c++std-lib-13499 for more.
-Proposed resolution:
- - -Change 21.1.3.1, p6 from
-- The two-argument members assign, eq, and lt are defined identically - to the built-in operators =, ==, and < respectively. --
to
-- The two-argument member assign is defined identically to - the built-in operators = and == respectively. The two - argument members eq and lt are defined identically to - the built-in operators == and < for type unsigned char. -- -
[Redmond: The LWG agreed with this general direction, but we - also need to change eq to be consistent with this change. - Post-Redmond: Martin provided wording.]
- -Section: 27.4.4.3 [lib.iostate.flags] Status: Review Submitter: Martin Sebor Date: 28 Jun 2004
- -The program below is required to compile but when run it typically -produces unexpected results due to the user-defined conversion from -std::cout or any object derived from basic_ios to void*. -
- -#include <cassert> - #include <iostream> - - int main () - { - assert (std::cin.tie () == std::cout); - // calls std::cout.ios::operator void*() - } -- -
Proposed resolution:
- --Replace std::basic_ios<charT, traits>::operator void*() with another -conversion operator to some unspecified type that is guaranteed not -to be convertible to any other type except for bool (a pointer-to-member -might be one such suitable type). In addition, make it clear that the -pointer type need not be a pointer to a complete type and when non-null, -the value need not be valid. -
- -Specifically, change in [lib.ios] the signature of
-operator void*() const; --
to
-operator unspecified_pointer_type () const; --
and change [lib.iostate.flags], p1 from
-operator void*() const; --
to
-operator unspecified_pointer_type() const; - -1- Returns: If fail() then a null pointer; otherwise some - non-null but not necessarily valid pointer to indicate - success. - -2- Note: The type named unspecified_pointer_type above is a pointer - to some unspecified, possibly incomplete type, that is guaranteed - not to be convertible to any other type except bool.(Footnote 1) - -- - Footnote 1: A pointer-to-member might be one such suitable type. -- -
[Redmond: 5-4 straw poll in favor of doing this.]
- -Section: 23.2.5 [lib.vector.bool] Status: Ready Submitter: Martin Sebor Date: 28 Jun 2004
- --The overloads of relational operators for vector<bool> specified -in [lib.vector.bool] are redundant (they are semantically identical -to those provided for the vector primary template) and may even be -diagnosed as ill-formed (refer to Daveed Vandevoorde's explanation -in c++std-lib-13647). -
- -Proposed resolution:
--Remove all overloads of overloads of relational operators for -vector<bool> from [lib.vector.bool]. -
-Section: 23 [lib.containers] Status: Open Submitter: Martin Sebor Date: 28 Jun 2004
- --The standard doesn't prohibit the destructors (or any other special -functions) of containers' elements invoked from a member function -of the container from "recursively" calling the same (or any other) -member function on the same container object, potentially while the -container is in an intermediate state, or even changing the state -of the container object while it is being modified. This may result -in some surprising (i.e., undefined) behavior. -
- -Read email thread starting with c++std-lib-13637 for more.
- -Proposed resolution:
- -Add to Container Requirements the following new paragraph:
- -Unless otherwise specified, the behavior of a program that - invokes a container member function f from a member function - g of the container's value_type on a container object c that - called g from its mutating member function h, is undefined. - I.e., if v is an element of c, directly or indirectly calling - c.h() from v.g() called from c.f(), is undefined. -- -
[Redmond: This is a real issue, but it's probably a clause 17 - issue, not clause 23. We get the same issue, for example, if we - try to destroy a stream from one of the stream's callback functions.]
- - -Section: 18.6.1 [lib.exception] Status: Open Submitter: Martin Sebor Date: 28 Jun 2004
- -[lib.exception] specifies the following:
-exception (const exception&) throw(); - exception& operator= (const exception&) throw(); - - -4- Effects: Copies an exception object. - -5- Notes: The effects of calling what() after assignment - are implementation-defined. -- -
-First, does the Note only apply to the assignment operator? If so, -what are the effects of calling what() on a copy of an object? Is -the returned pointer supposed to point to an identical copy of -the NTBS returned by what() called on the original object or not? -
- --Second, is this Note intended to extend to all the derived classes -in section 19? I.e., does the standard provide any guarantee for -the effects of what() called on a copy of any of the derived class -described in section 19? -
- --Finally, if the answer to the first question is no, I believe it -constitutes a defect since throwing an exception object typically -implies invoking the copy ctor on the object. If the answer is yes, -then I believe the standard ought to be clarified to spell out -exactly what the effects are on the copy (i.e., after the copy -ctor was called). -
- -[Redmond: Yes, this is fuzzy. The issue of derived classes is - fuzzy too.]
- -Proposed resolution:
-Section: 25.3.3.3 [lib.equal.range] Status: Review Submitter: Prateek R Karandikar Date: 29 Feb 1900
--There is no "Returns:" clause for std::equal_range, which returns non-void. -
-Proposed resolution:
-In 25.3.3.3 [lib.equal.range], change
-- Effects: Finds the largest subrange [i, j)... --
to
-- Returns: The largest subrange [i, j)... --
Section: 22.2.1.1 [lib.locale.ctype] Status: New Submitter: Martin Sebor Date: 1 Jul 2004
--Most ctype member functions come in two forms: one that operates -on a single character at a time and another form that operates -on a range of characters. Both forms are typically described by -a single Effects and/or Returns clause. -
--The Returns clause of each of the single-character non-virtual forms -suggests that the function calls the corresponding single character -virtual function, and that the array form calls the corresponding -virtual array form. Neither of the two forms of each virtual member -function is required to be implemented in terms of the other. -
--There are three problems: -
--1. One is that while the standard does suggest that each non-virtual -member function calls the corresponding form of the virtual function, -it doesn't actually explicitly require it. -
--Implementations that cache results from some of the virtual member -functions for some or all values of their arguments might want to -call the array form from the non-array form the first time to fill -the cache and avoid any or most subsequent virtual calls. Programs -that rely on each form of the virtual function being called from -the corresponding non-virtual function will see unexpected behavior -when using such implementations. -
--2. The second problem is that either form of each of the virtual -functions can be overridden by a user-defined function in a derived -class to return a value that is different from the one produced by -the virtual function of the alternate form that has not been -overriden. -
--Thus, it might be possible for, say, ctype::widen(c) to return one -value, while for ctype::widen(&c, &c + 1, &wc) to set -wc to another value. This is almost certainly not intended. Both -forms of every function should be required to return the same result -for the same character, otherwise the same program using an -implementation that calls one form of the functions will behave -differently than when using another implementation that calls the -other form of the function "under the hood." -
--3. The last problem is that the standard text fails to specify whether -one form of any of the virtual functions is permitted to be implemented -in terms of the other form or not, and if so, whether it is required -or permitted to call the overridden virtual function or not. -
--Thus, a program that overrides one of the virtual functions so that -it calls the other form which then calls the base member might end -up in an infinite loop if the called form of the base implementation -of the function in turn calls the other form. -
-Proposed resolution:
--To fix these problems I propose the following: -
--Add two paragraphs immediately after 22.2.1.1 [lib.locale.ctype], -p2, with the following text: -
- --3- Each ctype non-virtual member function that comes in two forms, - one that takes a range of elements of char_type, and another - that takes just a single element of char_type, is required to - call the corresponding form of the virtual member function - with the same value of char_type to obtain the result. The - result for the same argument may be cached and returned from - subsequent calls to either form of the non-virtual member - function with that argument. - - -4- For each ctype virtual member function that comes in two forms - (as explained above), the single element form is required to - produce the same result for a character c that the corresponding - array form produces for the array element with the same value as - c, and vice versa. - - -5- It is unspecified whether the array form of each virtual member - function calls the single-element virtual overload of the same - function in a loop, or whether the single element form calls - the array form with an array of a single element with the value - of its argument, or whether neither form calls the other. In - any case, an implementation is not permitted to make calls from - one form of any virtual member function to the corresponding - other form that is overridden in a derived class. -- -
Section: 27.6.2.5.4 [lib.ostream.inserters.character] Status: New Submitter: Martin Sebor Date: 1 Jul 2004
- --I think Footnote 297 is confused. The paragraph it applies to seems -quite clear in that widen() is only called if the object is not a char -stream (i.e., not basic_ostream<char>), so it's irrelevant what the -value of widen(c) is otherwise. -
-Proposed resolution:
--I propose to strike the Footnote. -
-Section: 25.1.1 [lib.alg.foreach] Status: New Submitter: Stephan T. Lavavej, Jaakko Jarvi Date: 9 Jul 2004
--It is not clear whether the function object passed to for_each is allowed to -modify the elements of the sequence being iterated over. -
- --for_each is classified without explanation in [lib.alg.nonmodifying], "25.1 -Non-modifying sequence operations". 'Non-modifying sequence operation' is -never defined. -
- --25(5) says: "If an algorithm's Effects section says that a value pointed to -by any iterator passed as an argument is modified, then that algorithm has -an additional type requirement: The type of that argument shall satisfy the -requirements of a mutable iterator (24.1)." -
- -for_each's Effects section does not mention whether arguments can be -modified:
- -- "Effects: Applies f to the result of dereferencing every iterator in the - range [first, last), starting from first and proceeding to last - 1." -+
LWG TC DR #127 is obsolete.
-Every other algorithm in [lib.alg.nonmodifying] is "really" non-modifying in -the sense that neither the algorithms themselves nor the function objects -passed to the algorithms may modify the sequences or elements in any way. -This DR affects only for_each. +Notice that the copy constructor and copy assignment operator should remain +as before and accept non-const auto_ptr& since they have effect on the form +of the implicitly declared copy constructor and copy assignment operator of +class that contains auto_ptr as member per 12.8/5,10:
+struct X { + // implicit X(X&) + // implicit X& operator=(X&) + auto_ptr<D> aptr_; +}; +
-We suspect that for_each's classification in "non-modifying sequence -operations" means that the algorithm itself does not inherently modify the -sequence or the elements in the sequence, but that the function object -passed to it may modify the elements it operates on. +In most cases this indicates about sloppy programming but preserves the +current auto_ptr behavior.
-The original STL document by Stepanov and Lee explicitly prohibited the -function object from modifying its argument. -The "obvious" implementation of for_each found in several standard library -implementations, however, does not impose this restriction. -As a result, we suspect that the use of for_each with function objects that modify -their arguments is wide-spread. -If the restriction was reinstated, all such code would become non-conforming. -Further, none of the other algorithms in the Standard -could serve the purpose of for_each (transform does not guarantee the order in -which its function object is called). +Dave Abrahams encouraged me to suggest fallback implementation in case that +my suggestion that involves removing of auto_ptr_ref will not be accepted. +In this case removing the obsolete conversion member to auto_ptr<Y> and +20.4.5.3/4,5 is still required in order to eliminate ambiguity in legal +cases. The two constructors that I suggested will co exist with the current +members but will make auto_ptr_ref obsolete in initialization contexts. +auto_ptr_ref will be effective in assignment contexts as suggested in DR +#127 and I can't see any serious exception safety issues in those cases +(although it's possible to synthesize such). auto_ptr_ref<X> semantics will +have to be revised to say that it strictly holds pointer of type X and not +reference to an auto_ptr for the favor of cases in which auto_ptr_ref<Y> is +constructed from auto_ptr<X> in which X is different from Y (i.e. assignment +from r-value derived to base).
--We suggest that the standard be clarified to explicitly allow the function object -passed to for_each modify its argument.
-Proposed resolution:
-Add the following sentence to the Effects in 25.1.1 [lib.alg.foreach]:
- --"f may apply non-constant functions through the dereferenced iterators -passed to it; if it does, the type of first shall satisfy the requirements -of a mutable iterator (24.1)." -- +
[Redmond: punt for the moment. We haven't decided yet whether we + want to fix auto_ptr for C++-0x, or remove it and replace it with + move_ptr and unique_ptr.]
Section: 24.1.3 [lib.forward.iterators] Status: New Submitter: Dave Abrahams Date: 9 Jul 2004
+Section: 23.2.4 [lib.vector], 23.3.1 [lib.map] Status: Ready Submitter: Thorsten Ottosen Date: 12 May 2004
-24.1/3 says:
-- Forward iterators satisfy all the requirements of the input and - output iterators and can be used whenever either kind is specified -+
To add slightly more convenience to vector<T> and map<Key,T> we should consider to add
+-The problem is that satisfying the requirements of output iterator -means that you can always assign *something* into the result of -dereferencing it. That makes almost all non-mutable forward -iterators non-conforming. I think we need to sever the refinement -relationship between forward iterator and output iterator. -
+Rationale:
-Proposed resolution:
-in 24.1/3, replace:
-- Forward iterators satisfy all the requirements of the input and - output iterators and can be used whenever either kind is specified. --
with
-- A forward iterator satisfies all the input iterator requirements. - A mutable forward iterator satisfies all the output iterator - requirements. --
Section: 24.1.3 [lib.forward.iterators] Status: New Submitter: Dave Abrahams Date: 11 Jul 2004
--The Forward Iterator requirements table contains the following: -
-expression return type operational precondition - semantics - ========== ================== =========== ========================== - a->m U& if X is mutable, (*a).m pre: (*a).m is well-defined. - otherwise const U& +
Proposed resolution:
+In 23.2.4 [lib.vector], add the following to the vector + synopsis after "element access" and before "modifiers":
+// [lib.vector.data] data access + pointer data(); + const_pointer data() const;-
-The first line is exactly right. The second line is wrong. Basically -it implies that the const-ness of the iterator affects the const-ness -of referenced members. But Paragraph 11 of [lib.iterator.requirements] says: -
- +Add a new subsection of 23.2.4 [lib.vector]:
- In the following sections, a and b denote values of type const X, n - denotes a value of the difference type Distance, u, tmp, and m - denote identifiers, r denotes a value of X&, t denotes a value of - value type T, o denotes a value of some type that is writable to - the output iterator. +-23.2.4.x vector data access
+pointer data(); + const_pointer data() const; ++Returns: A pointer such that [data(), data() + size()) is a valid + range. For a non-empty vector, data() == &front().
+Complexity: Constant time.
+Throws: Nothing.
AFAICT if we need the second line at all, it should read the same -as the first line.
- -Related issue: 478
-Proposed resolution:
-Section: 24.1.3 [lib.forward.iterators] Status: New Submitter: Dave Abrahams Date: 11 Jul 2004
--The Forward Iterator requirements table contains the following: -
-expression return type operational precondition - semantics - ========== ================== =========== ========================== - a->m U& if X is mutable, (*a).m pre: (*a).m is well-defined. - otherwise const U& - - r->m U& (*r).m pre: (*r).m is well-defined. +In 23.3.1 [lib.map], add the following to the map +synopsis immediately after the line for operator[]:
+T& at(const key_type& x); + const T& at(const key_type& x) const;-The second line may be unnecessary. Paragraph 11 of - [lib.iterator.requirements] says: -
- -- In the following sections, a and b denote values of type const X, n - denotes a value of the difference type Distance, u, tmp, and m - denote identifiers, r denotes a value of X&, t denotes a value of - value type T, o denotes a value of some type that is writable to - the output iterator. -- --Because operators can be overloaded on an iterator's const-ness, the -current requirements allow iterators to make many of the operations -specified using the identifiers a and b invalid for non-const -iterators. Rather than expanding the tables, I think the right -answer is to change -
+Add the following to 23.3.1.2 [lib.map.access]:
- "const X" -+T& at(const key_type& x); + const T& at(const key_type& x) const; +-to
+Returns: A reference to the element whose key is equivalent + to x, if such an element is present in the map.
+Throws: out_of_range if no such element is present.
-- "X or const X"-in paragraph 11 of [lib.iterator.requirements].
- -Related issue: 477
-Proposed resolution:
+Rationale:
+Neither of these additions provides any new functionality but the + LWG agreed that they are convenient, especially for novices. The + exception type chosen for at, std::out_of_range, + was chosen to match vector::at.
-479. Container requirements and placement new
Section: 23.1 [lib.container.requirements] Status: New Submitter: Herb Sutter Date: 1 Aug 2004
-Nothing in the standard appears to make this program ill-formed:
- -struct C { - void* operator new( size_t s ) { return ::operator new( s ); } - // NOTE: this hides in-place and nothrow new - }; - - int main() { - vector<C> v; - v.push_back( C() ); - } -+465. Contents of <ciso646>
Section: 17.4.1.2 [lib.headers] Status: Ready Submitter: Steve Clamage Date: 3 Jun 2004
+C header <iso646.h> defines macros for some operators, such as +not_eq for !=.
-Is that intentional? We should clarify whether or not we intended - to require containers to support types that define their own special - versions of operator new.
+Section 17.4.1.2 [lib.headers] "Headers" says that except as noted in +clauses 18 through 27, the <cname> C++ header contents are the same +as the C header <name.h>. In particular, table 12 lists +<ciso646> as a C++ header.
-Proposed resolution:
-
-480. unary_function and binary_function should have protected nonvirtual destructors
Section: 20.3.1 [lib.base] Status: New Submitter: Joe Gottman Date: 19 Aug 2004
-The classes std::unary_function and std::binary_function are both -designed to be inherited from but contain no virtual functions. This -makes it too easy for a novice programmer to write code like -binary_function<int, int, int> *p = new plus<int>; delete p;
- -There are two common ways to prevent this source of undefined -behavior: give the base class a public virtual destructor, or give it -a protected nonvirtual destructor. Since unary_function and -binary_function have no other virtual functions, (note in particular -the absence of an operator()() ), it would cost too much to give them -public virtual destructors. Therefore, they should be given protected -nonvirtual destructors.
-Proposed resolution:
-Change Paragraph 20.3.1 of the Standard from
-template <class Arg, class Result> - struct unary_function { - typedef Arg argument_type; - typedef Result result_type; - }; ++I don't find any other mention of <ciso646>, or any mention of +<iso646.h>, in clauses 17 thorough 27. That implies that the +contents of <ciso646> are the same as C header <iso646.h>.
- template <class Arg1, class Arg2, class Result> - struct binary_function { - typedef Arg1 first_argument_type; - typedef Arg2 second_argument_type; - typedef Result result_type; - }; -Annex C (informative, not normative) in [diff.header.iso646.h] C.2.2.2 +"Header <iso646.h>" says that the alternative tokens are not +defined as macros in <ciso646>, but does not mention the contents +of <iso646.h>.
-to
-template <class Arg, class Result> - struct unary_function { - typedef Arg argument_type; - typedef Result result_type; - protected: - ~unary_function() {} - }; +-I don't find any normative text to support C.2.2.2.
- template <class Arg1, class Arg2, class Result> - struct binary_function { - typedef Arg1 first_argument_type; - typedef Arg2 second_argument_type; - typedef Result result_type; - protected: - ~binary_function() {} - }; -
-481. unique's effects on the range [result, last)
Section: 25.2.8 [lib.alg.unique] Status: New Submitter: Andrew Koenig Date: 30 Aug 2004
--The standard says that unique(first, last) "eliminates all but the -first element from every consecutive group of equal elements" in -[first, last) and returns "the end of the resulting range". So a -postcondition is that [first, result) is the same as the old [first, -last) except that duplicates have been eliminated. -
+Proposed resolution:
+Add to section 17.4.1.2 Headers [lib.headers] a new paragraph after + paragraph 6 (the one about functions must be functions):
-What postconditions are there on the range [result, last)? One - might argue that the standard says nothing about those values, so - they can be anything. One might also argue that the standard - doesn't permit those values to be changed, so they must not be. - Should the standard say something explicit one way or the other?
++-Identifiers that are keywords or operators in C++ shall not be defined +as macros in C++ standard library headers. +[Footnote:In particular, including the standard header <iso646.h> +or <ciso646> has no effect.
+Proposed resolution:
--
-
-482. Swapping pairs
Section: 20.2.2 [lib.pairs], 25.2.2 [lib.alg.swap] Status: New Submitter: Andrew Koenig Date: 14 Sep 2004
-(Based on recent comp.std.c++ discussion)
+[post-Redmond: Steve provided wording.]
-Pair (and tuple) should specialize std::swap to work in terms of -std::swap on their components. For example, there's no obvious reason -why swapping two objects of type pair<vector<int>, -list<double> > should not take O(1).
-Proposed resolution:
-484. Convertible to T
Section: 24.1.1 [lib.input.iterators] Status: New Submitter: Chris Date: 16 Sep 2004
-From comp.std.c++:
- +466. basic_string ctor should prevent null pointer error
Section: 21.3.1 [lib.string.cons] Status: Open Submitter: Daniel Frey Date: 10 Jun 2004
-I note that given an input iterator a for type T, -then *a only has to be "convertable to T", not actually of type T. +Today, my colleagues and me wasted a lot of time. After some time, I +found the problem. It could be reduced to the following short example:
-Firstly, I can't seem to find an exact definition of "convertable to T". -While I assume it is the obvious definition (an implicit conversion), I -can't find an exact definition. Is there one?
- -Slightly more worryingly, there doesn't seem to be any restriction on -the this type, other than it is "convertable to T". Consider two input -iterators a and b. I would personally assume that most people would -expect *a==*b would perform T(*a)==T(*b), however it doesn't seem that -the standard requires that, and that whatever type *a is (call it U) -could have == defined on it with totally different symantics and still -be a valid inputer iterator.
- -Is this a correct reading? When using input iterators should I write -T(*a) all over the place to be sure that the object i'm using is the -class I expect?
+#include <string> + int main() { std::string( 0 ); } +-This is especially a nuisance for operations that are defined to be - "convertible to bool". (This is probably allowed so that - implementations could return say an int and avoid an unnessary - conversion. However all implementations I have seen simply return a - bool anyway. Typical implemtations of STL algorithms just write - things like while(a!=b && *a!=0). But strictly - speaking, there are lots of types that are convertible to T but - that also overload the appropriate operators so this doesn't behave - as expected.
+The problem is that the tested compilers (GCC 2.95.2, GCC 3.3.1 and +Comeau online) compile the above without errors or warnings! The +programs (at least for the GCC) resulted in a SEGV.
-If we want to make code like this legal (which most people seem to - expect), then we'll need to tighten up what we mean by "convertible - to T".
+I know that the standard explicitly states that the ctor of string +requires a char* which is not zero. STLs could easily detect the above +case with a private ctor for basic_string which takes a single 'int' +argument. This would catch the above code at compile time and would not +ambiguate any other legal ctors.
Proposed resolution:
--
-
-485. output iterator insufficently constrained
Section: 24.1.2 [lib.output.iterators] Status: New Submitter: Chris Date: 13 Oct 2004
--The note on 24.1.2 Output iterators insufficently limits what can be -performed on output iterators. While it requires that each iterator is -progressed through only once and that each iterator is written to only -once, it does not require the following things:
- -Note: Here it is assumed that x is an output iterator of type X which -has not yet been assigned to.
+[Redmond: No great enthusiasm for doing this. If we do, + however, we want to do it for all places that take charT* + pointers, not just the single-argument constructor. The other + question is whether we want to catch this at compile time (in which + case we catch the error of a literal 0, but not an expression whose + value is a null pointer), at run time, or both.]
-a) That each value of the output iterator is written to: -The standard allows: -++x; ++x; ++x; -
+
+467. char_traits::lt(), compare(), and memcmp()
Section: 21.1.3.1 [lib.char.traits.specializations.char] Status: Ready Submitter: Martin Sebor Date: 28 Jun 2004
-b) That assignments to the output iterator are made in order -X a(x); ++a; *a=1; *x=2; is allowed +Table 37 describes the requirements on Traits::compare() in terms of +those on Traits::lt(). 21.1.3.1, p6 requires char_traits<char>::lt() +to yield the same result as operator<(char, char).
-c) Chains of output iterators cannot be constructed: -X a(x); ++a; X b(a); ++b; X c(b); ++c; is allowed, and under the current -wording (I believe) x,a,b,c could be written to in any order. +Most, if not all, implementations of char_traits<char>::compare() +call memcmp() for efficiency. However, the C standard requires both +memcmp() and strcmp() to interpret characters under comparison as +unsigned, regardless of the signedness of char. As a result, all +these char_traits implementations fail to meet the requirement +imposed by Table 37 on compare() when char is signed.
-I do not believe this was the intension of the standard?
+ +Read email thread starting with c++std-lib-13499 for more.
Proposed resolution:
-Add to the note:
-"The values of an output iterator must be assigned to in the order they -are generated. It is undefined to progress forward more than once from a -value of an output iterator which has not yet been assigned."
-This is I believe the intension of the existing text. The "progress -forward once" is allowed so that "*r++=t" is allowed. It may be prefered -to instead allow something more along the lines of:
+Change 21.1.3.1, p6 from
++ The two-argument members assign, eq, and lt are defined identically + to the built-in operators =, ==, and < respectively. ++to
++ The two-argument member assign is defined identically to + the built-in operator =. The two + argument members eq and lt are defined identically to + the built-in operators == and < for type unsigned char. ++ +[Redmond: The LWG agreed with this general direction, but we + also need to change eq to be consistent with this change. + Post-Redmond: Martin provided wording.]
-"The values of an output iterator must be assigned to in the order they -are generated. With the exception of '*r++=t', an iterator must always -be assigned to before it is incremented".
-487. Allocator::construct is too limiting
Section: 20.1.5 [lib.allocator.requirements] Status: New Submitter: Dhruv Matani Date: 17 Oct 2004
--The standard's version of allocator::construct(pointer, -const_reference) severely limits what you can construct using this -function. Say you can construct a socket from a file descriptor. Now, -using this syntax, I first have to manually construct a socket from -the fd, and then pass the constructed socket to the construct() -function so it will just to an uninitialized copy of the socket I -manually constructed. Now it may not always be possible to copy -construct a socket eh! So, I feel that the changes should go in the -allocator::construct(), making it: -
-template<typename T> - struct allocator{ - template<typename T1> - void construct(pointer T1 const& rt1); - }; -+468. unexpected consequences of ios_base::operator void*()
Section: 27.4.4.3 [lib.iostate.flags] Status: Ready Submitter: Martin Sebor Date: 28 Jun 2004
--Now, the ctor of the class T which matches the one that takes a T1 can -be called! Doesn't that sound great? -
-Proposed resolution:
--
-
-488. rotate throws away useful information
Section: 25.2.10 [lib.alg.rotate] Status: New Submitter: Howard Hinnant Date: 22 Nov 2004
--rotate takes 3 iterators: first, middle and last which point into a -sequence, and rearranges the sequence such that the subrange [middle, -last) is now at the beginning of the sequence and the subrange [first, -middle) follows. The return type is void. +
The program below is required to compile but when run it typically +produces unexpected results due to the user-defined conversion from +std::cout or any object derived from basic_ios to void*.
--In many use cases of rotate, the client needs to know where the -subrange [first, middle) starts after the rotate is performed. This -might look like: -
-rotate(first, middle, last); - Iterator i = advance(first, distance(middle, last)); -+#include <cassert> + #include <iostream> --Unless the iterators are random access, the computation to find the -start of the subrange [first, middle) has linear complexity. However, -it is not difficult for rotate to return this information with -negligible additional computation expense. So the client could code: -
-Iterator i = rotate(first, middle, last); + int main () + { + assert (std::cin.tie () == std::cout); + // calls std::cout.ios::operator void*() + }--and the resulting program becomes significantly more efficient. -
+Proposed resolution:
-While the backwards compatibility hit with this change is not zero, it -is very small (similar to that of lwg
-), and there is -a significant benefit to the change. +Replace std::basic_ios<charT, traits>::operator void*() with another +conversion operator to some unspecified type that is guaranteed not +to be convertible to any other type except for bool (a pointer-to-member +might be one such suitable type). In addition, make it clear that the +pointer type need not be a pointer to a complete type and when non-null, +the value need not be valid. Proposed resolution:
-In 25p2, change:
-template<class ForwardIterator> - void rotate(ForwardIterator first, ForwardIterator middle, - ForwardIterator last); +Specifically, change in [lib.ios] the signature of
+operator void*() const;- -to:
- -template<class ForwardIterator> - ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, - ForwardIterator last); +to
+operator unspecified-bool-type() const;- -In 25.2.10, change:
- -template<class ForwardIterator> - void rotate(ForwardIterator first, ForwardIterator middle, - ForwardIterator last); +and change [lib.iostate.flags], p1 from
+operator void*() const;+to
+operator unspecified-bool-type() const; -to:
+ -1- Returns: if fail() then a value that will evaluate false in a + boolean context; otherwise a value that will evaluate true in a + boolean context. The value type returned shall not be + convertible to int. -template<class ForwardIterator> - ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, - ForwardIterator last); + -2- [Note: This conversion can be used in contexts where a bool + is expected (e.g., an if condition); however, implicit + conversions (e.g., to int) that can occur with bool are not + allowed, eliminating some sources of user error. One possible + implementation choice for this type is pointer-to-member. - end + note]-In 25.2.10 insert a new paragraph after p1:
+[Redmond: 5-4 straw poll in favor of doing this.]
+[Lillehammer: Doug provided revised wording for + "unspecified-bool-type".]
--Returns: advance(first, distance(middle, last)).
-
-489. std::remove / std::remove_if wrongly specified
Section: 25.2.7 [lib.alg.remove] Status: New Submitter: Thomas Mang Date: 12 Dec 2004
-In Section 25.2.7 [lib.alg.remove], paragraphs 1 to 5 describe the -behavior of the mutating sequence operations std::remove and -std::remove_if. However, the wording does not reflect the intended -behavior [Note: See definition of intended behavior below] of these -algorithms, as it is known to the C++ community [1]. +
470. accessing containers from their elements' special functions
Section: 23 [lib.containers] Status: Open Submitter: Martin Sebor Date: 28 Jun 2004
+ ++The standard doesn't prohibit the destructors (or any other special +functions) of containers' elements invoked from a member function +of the container from "recursively" calling the same (or any other) +member function on the same container object, potentially while the +container is in an intermediate state, or even changing the state +of the container object while it is being modified. This may result +in some surprising (i.e., undefined) behavior.
+Read email thread starting with c++std-lib-13637 for more.
+ +Proposed resolution:
+Add to Container Requirements the following new paragraph:
-1) Analysis of current wording:
+Unless otherwise specified, the behavior of a program that + invokes a container member function f from a member function + g of the container's value_type on a container object c that + called g from its mutating member function h, is undefined. + I.e., if v is an element of c, directly or indirectly calling + c.h() from v.g() called from c.f(), is undefined. ++[Redmond: This is a real issue, but it's probably a clause 17 + issue, not clause 23. We get the same issue, for example, if we + try to destroy a stream from one of the stream's callback functions.]
+ -25.2.7 [lib.alg.remove], paragraph 2:
+
+471. result of what() implementation-defined
Section: 18.6.1 [lib.exception] Status: Open Submitter: Martin Sebor Date: 28 Jun 2004
-Current wording says: -"Effects: Eliminates all the elements referred to by iterator i in the -range [first, last) for which the following corresponding conditions -hold: *i == value, pred(*i) != false."
+[lib.exception] specifies the following:
+exception (const exception&) throw(); + exception& operator= (const exception&) throw(); --This sentences expresses specifically that all elements denoted by the -(original) range [first, last) for which the corresponding condition -hold will be eliminated. Since there is no formal definition of the term -"eliminate" provided, the meaning of "eliminate" in everyday language -implies that as postcondition, no element in the range denoted by -[first, last) will hold the corresponding condition on reiteration over -the range [first, last). -
+ -4- Effects: Copies an exception object. + -5- Notes: The effects of calling what() after assignment + are implementation-defined. +-However, this is neither the intent [Note: See definition of intended -behavior below] nor a general possible approach. It can be easily proven -that if all elements of the original range[first, last) will hold the -condition, it is not possible to substitute them by an element for which -the condition will not hold. +First, does the Note only apply to the assignment operator? If so, +what are the effects of calling what() on a copy of an object? Is +the returned pointer supposed to point to an identical copy of +the NTBS returned by what() called on the original object or not?
- -25.2.7 [lib.alg.remove], paragraph 3:
--Current wording says: -"Returns: The end of the resulting range." +Second, is this Note intended to extend to all the derived classes +in section 19? I.e., does the standard provide any guarantee for +the effects of what() called on a copy of any of the derived class +described in section 19?
-The resulting range is not specified. In combination with 25.2.7 -[lib.alg.remove], paragraph 2, the only reasonable interpretation of -this so-called resulting range is the range [first,last) - thus -returning always the ForwardIterator 'last' parameter. +Finally, if the answer to the first question is no, I believe it +constitutes a defect since throwing an exception object typically +implies invoking the copy ctor on the object. If the answer is yes, +then I believe the standard ought to be clarified to spell out +exactly what the effects are on the copy (i.e., after the copy +ctor was called).
+[Redmond: Yes, this is fuzzy. The issue of derived classes is + fuzzy too.]
+Proposed resolution:
+
+473. underspecified ctype calls
Section: 22.2.1.1 [lib.locale.ctype] Status: Open Submitter: Martin Sebor Date: 1 Jul 2004
-25.2.7 [lib.alg.remove], paragraph 4: +Most ctype member functions come in two forms: one that operates +on a single character at a time and another form that operates +on a range of characters. Both forms are typically described by +a single Effects and/or Returns clause.
--Current wording says: -"Notes: Stable: the relative order of the elements that are not removed -is the same as their relative order in the original range" +The Returns clause of each of the single-character non-virtual forms +suggests that the function calls the corresponding single character +virtual function, and that the array form calls the corresponding +virtual array form. Neither of the two forms of each virtual member +function is required to be implemented in terms of the other.
--This sentences makes use of the term "removed", which is neither -specified, nor used in a previous paragraph (which uses the term -"eliminate"), nor unamgiuously separated from the name of the algorithm. +There are three problems:
- - -2) Description of intended behavior:
--For the rest of this Defect Report, it is assumed that the intended -behavior was that all elements of the range [first, last) which do not -hold the condition *i == value (std::remove) or pred(*i) != false -(std::remove_if)], call them s-elements [Note: s...stay], will be placed -into a contiguous subrange of [first, last), denoted by the iterators -[first, return value). The number of elements in the resulting range -[first, return value) shall be equal to the number of s-elements in the -original range [first, last). The relative order of the elements in the -resulting subrange[first, return value) shall be the same as the -relative order of the corresponding elements in the original range. It -is undefined whether any elements in the resulting subrange [return -value, last) will hold the corresponding condition, or not. +1. One is that while the standard does suggest that each non-virtual +member function calls the corresponding form of the virtual function, +it doesn't actually explicitly require it.
--All implementations known to the author of this Defect Report comply -with this intent. Since the intent of the behavior (contrary to the -current wording) is also described in various utility references serving -the C++ community [1], it is not expected that fixing the paragraphs -will influence current code - unless the code relies on the behavior as -it is described by current wording and the implementation indeed -reflects the current wording, and not the intent. +Implementations that cache results from some of the virtual member +functions for some or all values of their arguments might want to +call the array form from the non-array form the first time to fill +the cache and avoid any or most subsequent virtual calls. Programs +that rely on each form of the virtual function being called from +the corresponding non-virtual function will see unexpected behavior +when using such implementations.
- - - -3) Proposed fixes:
- - -Change 25.2.7 [lib.alg.remove], paragraph 2 to:
--"Effect: Places all the elements referred to by iterator i in the range -[first, last) for which the following corresponding conditions hold : -!(*i == value), pred(*i) == false into the subrange [first, k) of the -original range, where k shall denote a value of type ForwardIterator. It -is undefined whether any elements in the resulting subrange [k, last) -will hold the corresponding condition, or not." +2. The second problem is that either form of each of the virtual +functions can be overridden by a user-defined function in a derived +class to return a value that is different from the one produced by +the virtual function of the alternate form that has not been +overriden.
- -Comments to the new wording:
--a) "Places" has no special meaning, and the everyday language meaning -should fit. -b) The corresponding conditions were negated compared to the current -wording, becaue the new wording requires it. -c) The wording "of the original range" might be redundant, since any -subrange starting at 'first' and containing no more elements than the -original range is implicitly a subrange of the original range [first, -last). -d) The iterator k was introduced instead of "return value" in order to -avoid a cyclic dependency on 25.2.7/3. The wording ", where k shall -denote a value of type ForwardIterator" might be redundant, because it -follows implicitly by 25.2.7/3. -e) "Places" does, in the author's opinion, explicitly forbid duplicating -any element holding the corresponding condition in the original range -[first, last) within the resulting range [first, k). If there is doubt -this term might be not unambiguous regarding this, it is suggested that -k is specified more closely by the following wording: "k shall denote a -value of type ForwardIterator [Note: see d)] so that k - first is equal -to the number of elements in the original range [first, last) for which -the corresponding condition did hold". This could also be expressed as a -separate paragraph "Postcondition:" -f) The senctence "It is undefined whether any elements in the resulting -subrange [k, last) will hold the corresponding condition, or not." was -added consciously so the term "Places" does not imply if the original -range [first, last) contains n elements holding the corresponding -condition, the identical range[first, last) will also contain exactly n -elements holding the corresponding condition after application of the -algorithm. +Thus, it might be possible for, say, ctype::widen(c) to return one +value, while for ctype::widen(&c, &c + 1, &wc) to set +wc to another value. This is almost certainly not intended. Both +forms of every function should be required to return the same result +for the same character, otherwise the same program using an +implementation that calls one form of the functions will behave +differently than when using another implementation that calls the +other form of the function "under the hood."
--Change 25.2.7 [lib.alg.remove], paragraph 3 to: - -"Returns: The iterator k." +3. The last problem is that the standard text fails to specify whether +one form of any of the virtual functions is permitted to be implemented +in terms of the other form or not, and if so, whether it is required +or permitted to call the overridden virtual function or not.
--Change 25.2.7 [lib.alg.remove], paragraph 4 to: - -"Notes: Stable: the relative order of the elements that are placed into -the subrange [first, return value) shall be the same as their relative -order was in the original range [first, last) prior to application of -the algorithm." +Thus, a program that overrides one of the virtual functions so that +it calls the other form which then calls the base member might end +up in an infinite loop if the called form of the base implementation +of the function in turn calls the other form.
+Proposed resolution:
-Comments to the new wording: -
+Lillehammer: Part of this isn't a real problem. We already talk about +caching. 22.1.1/6 But part is a real problem. ctype virtuals may call +each other, so users don't know which ones to override to avoid avoid +infinite loops. --a) the wording "was ... prior to application of the algorithm" is used -to explicitly distinguish the original range not only by means of -iterators, but also by a 'chronological' factor from the resulting range -[first, return value). It might be redundant. -
+This is a problem for all facet virtuals, not just ctype virtuals, +so we probably want a blanket statement in clause 22 for all +facets. The LWG is leaning toward a blanket prohibition, that a +facet's virtuals may never call each other. We might want to do that +in clause 27 too, for that matter. A review is necessary. Bill will +provide wording.
+
+474. confusing Footnote 297
Section: 27.6.2.5.4 [lib.ostream.inserters.character] Status: Ready Submitter: Martin Sebor Date: 1 Jul 2004
-[1]: -The wording of these references is not always unambiguous, and provided -examples partially contradict verbal description of the algorithms, -because the verbal description resembles the problematic wording of -ISO/IEC 14882:2003. +I think Footnote 297 is confused. The paragraph it applies to seems +quite clear in that widen() is only called if the object is not a char +stream (i.e., not basic_ostream<char>), so it's irrelevant what the +value of widen(c) is otherwise.
Proposed resolution:
+I propose to strike the Footnote.
-490. std::unique wrongly specified
Section: 25.2.8 [lib.alg.unique] Status: New Submitter: Thomas Mang Date: 12 Dec 2004
-In Section 25.2.8 [lib.alg.unique], paragraphs 1 to 3 describe the -behavior of the mutating sequence operation std::unique. However, the -wording does not reflect the intended behavior [Note: See definition of -intended behavior below] of these algorithms, as it is known to the C++ -community [1].
- - - -1) Analysis of current wording:
- - -25.2.8 [lib.alg.unique], paragraph 1:
- +475. May the function object passed to for_each modify the elements of the iterated sequence?
Section: 25.1.1 [lib.alg.foreach] Status: Review Submitter: Stephan T. Lavavej, Jaakko Jarvi Date: 9 Jul 2004
-Current wording says: -"Effects: Eliminates all but the first element from every consecutive -group of equal elements referred to by the iterator i in the range -[first, last) for which the following corresponding conditions hold: *i -== *(i - 1) or pred(*i, *(i -1)) != false" +It is not clear whether the function object passed to for_each is allowed to +modify the elements of the sequence being iterated over.
-This sentences expresses specifically that all elements denoted by the -(original) range [first, last) which are not but the first element from -a consecutive group of equal elements (where equality is defined as *i -== *(i - 1) or pred(*i, *(i - 1)) ! = false) [Note: See DR 202], call -them r-elements [Note: r...remove], will be eliminated. Since there is -no formal definition of the term "eliminate" provided, it is undefined -how this "elimination" takes place. But the meaning of "eliminate" in -everyday language seems to disallow explicitly that after application of -the algorithm, any r-element will remain at any position of the range -[first, last) [2]. +for_each is classified without explanation in [lib.alg.nonmodifying], "25.1 +Non-modifying sequence operations". 'Non-modifying sequence operation' is +never defined.
-Another defect in the current wording concerns the iterators used to -compare two elements for equality: The current wording contains the -expression "(i - 1)", which is not covered by 25/9 [Note: See DR -submitted by Thomas Mang regarding invalid iterator arithmetic -expressions]. +25(5) says: "If an algorithm's Effects section says that a value pointed to +by any iterator passed as an argument is modified, then that algorithm has +an additional type requirement: The type of that argument shall satisfy the +requirements of a mutable iterator (24.1)."
+for_each's Effects section does not mention whether arguments can be +modified:
--25.2.8 [lib.alg.unique], paragraph 2: -
-Current wording says: -"Returns: The end of the resulting range."
++ "Effects: Applies f to the result of dereferencing every iterator in the + range [first, last), starting from first and proceeding to last - 1." +-The resulting range is not specified. In combination with 25.2.8 -[lib.alg.unique], paragraph 1, one reasonable interpretation (in the -author's opinion even the only possible interpretation) of this -so-called resulting range is the range [first, last) - thus returning -always the ForwardIterator 'last' parameter. +Every other algorithm in [lib.alg.nonmodifying] is "really" non-modifying in +the sense that neither the algorithms themselves nor the function objects +passed to the algorithms may modify the sequences or elements in any way. +This DR affects only for_each.
-2) Description of intended behavior:
--For the rest of this Defect Report, it is assumed that the intended -behavior was that all elements denoted by the original range [first, -last) which are the first element from a consecutive group of elements -for which the corresponding conditions: *(i-1) == *i (for the version of -unique without a predicate argument) or pred(*(i-1), *i) ! = false (for -the version of unique with a predicate argument) [Note: If such a group -of elements consists of only a single element, this is also considered -the first element] [Note: See resolutions of DR 202], call them -s-elements [Note: s...stay], will be placed into a contiguous subrange -of [first, last), denoted by the iterators [first, return value). The -number of elements in the resulting range [first, return value) shall be -equal to the number of s-elements in the original range [first, last). -Invalid iterator arithmetic expressions are expected to be resolved as -proposed in DR submitted by Thomas Mang regarding invalid iterator -arithmetic expressions. It is also assumed by the author that the -relative order of the elements in the resulting subrange [first, return -value) shall be the same as the relative order of the corresponding -elements (the s-elements) in the original range [Note: If this was not -intended behavior, the additional proposed paragraph about stable order -will certainly become obsolete]. -Furthermore, the resolutions of DR 202 are partially considered. +We suspect that for_each's classification in "non-modifying sequence +operations" means that the algorithm itself does not inherently modify the +sequence or the elements in the sequence, but that the function object +passed to it may modify the elements it operates on.
-All implementations known to the author of this Defect Report comply -with this intent [Note: Except possible effects of DR 202]. Since this -intent of the behavior (contrary to the current wording) is also -described in various utility references serving the C++ community [1], -it is not expected that fixing the paragraphs will influence current -code [Note: Except possible effects of DR 202] - unless the code relies -on the behavior as it is described by current wording and the -implementation indeed reflects the current wording, and not the intent. +The original STL document by Stepanov and Lee explicitly prohibited the +function object from modifying its argument. +The "obvious" implementation of for_each found in several standard library +implementations, however, does not impose this restriction. +As a result, we suspect that the use of for_each with function objects that modify +their arguments is wide-spread. +If the restriction was reinstated, all such code would become non-conforming. +Further, none of the other algorithms in the Standard +could serve the purpose of for_each (transform does not guarantee the order in +which its function object is called).
- - -3) Proposed fixes:
--Change 25.2.8 [lib.alg.unique], paragraph 1 to: +We suggest that the standard be clarified to explicitly allow the function object +passed to for_each modify its argument.
+ +Proposed resolution:
+Add a nonnormative note to the Effects in 25.1.1 [lib.alg.foreach]: If +the type of 'first' satisfies the requirements of a mutable iterator, +'f' may apply nonconstant functions through the dereferenced iterators +passed to it.
+Rationale:
+The LWG believes that nothing in the standard prohibits function + objects that modify the sequence elements. The problem is that + for_each is in a secion entitled "nonmutating algorithms", and the + title may be confusing. A nonnormative note should clarify that.
+
+478. Should forward iterator requirements table have a line for r->m?
Section: 24.1.3 [lib.forward.iterators] Status: Review Submitter: Dave Abrahams Date: 11 Jul 2004
-"Effect: Places the first element from every consecutive group of -elements, referred to by the iterator i in the range [first, last), for -which the following conditions hold: *(i-1) == *i (for the version of -unique without a predicate argument) or pred(*(i -1), *i) != false (for -the version of unique with a predicate argument), into the subrange -[first, k) of the original range, where k shall denote a value of type -ForwardIterator." +The Forward Iterator requirements table contains the following:
+expression return type operational precondition + semantics + ========== ================== =========== ========================== + a->m U& if X is mutable, (*a).m pre: (*a).m is well-defined. + otherwise const U& --Comments to the new wording:
+ r->m U& (*r).m pre: (*r).m is well-defined. +-a) The new wording was influenced by the resolutions of DR 202. If DR -202 is resolved in another way, the proposed wording need also -additional review. -b) "Places" has no special meaning, and the everyday language meaning -should fit. -c) The expression "(i - 1)" was left, but is expected that DR submitted -by Thomas Mang regarding invalid iterator arithmetic expressions will -take this into account. -d) The wording "(for the version of unique without a predicate -argument)" and "(for the version of unique with a predicate argument)" -was added consciously for clarity and is in resemblence with current -23.2.2.4 [lib.list.ops], paragraph 19. It might be considered redundant. -e) The wording "of the original range" might be redundant, since any -subrange starting at first and containing no more elements than the -original range is implicitly a subrange of the original range [first, -last). -f) The iterator k was introduced instead of "return value" in order to -avoid a cyclic dependency on 25.2.8 [lib.alg.unique], paragraph 2. The -wording ", where k shall denote a value of type ForwardIterator" might -be redundant, because it follows implicitly by 25.2.8 [lib.alg.unique], -paragraph 2. -g) "Places" does, in the author's opinion, explicitly forbid duplicating -any s-element in the original range [first, last) within the resulting -range [first, k). If there is doubt this term might be not unambiguous -regarding this, it is suggested that k is specified more closely by the -following wording: "k shall denote a value of type ForwardIterator -[Note: See f)] so that k - first is equal to the number of elements in -the original range [first, last) being the first element from every -consecutive group of elements for which the corresponding condition did -hold". This could also be expressed as a separate paragraph -"Postcondition:". -h) If it is considered that the wording is unclear whether it declares -the element of a group which consists of only a single element -implicitly to be the first element of this group [Note: Such an -interpretation could eventually arise especially in case last - first == -1] , the following additional sentence is proposed: "If such a group of -elements consists of only a single element, this element is also -considered the first element." -
- --Change 25.2.8 [lib.alg.unique], paragraph 2 to: -"Returns: The iterator k." -
- --Add a separate paragraph "Notes:" as 25.2.8 [lib.alg.unique], paragraph -2a or 3a, or a separate paragraph "Postcondition:" before 25.2.8 -[lib.alg.unique], paragraph 2 (wording inside {} shall be eliminated if -the preceding expressions are used, or the preceding expressions shall -be eliminated if wording inside {} is used): -
- --"Notes:{Postcondition:} Stable: the relative order of the elements that -are placed into the subrange [first, return value {k}) shall be the same -as their relative order was in the original range [first, last) prior to -application of the algorithm." +
The second line may be unnecessary. Paragraph 11 of + [lib.iterator.requirements] says:
-Comments to the new wording:
++ In the following sections, a and b denote values of type const X, n + denotes a value of the difference type Distance, u, tmp, and m + denote identifiers, r denotes a value of X&, t denotes a value of + value type T, o denotes a value of some type that is writable to + the output iterator. +-a) It is assumed by the author that the algorithm was intended to be -stable. -In case this was not the intent, this paragraph becomes certainly -obsolete. -b) The wording "was ... prior to application of the algorithm" is used -to explicitly distinguish the original range not only by means of -iterators, but also by a 'chronological' factor from the resulting range -[first, return value). It might be redundant. -
+Because operators can be overloaded on an iterator's const-ness, the +current requirements allow iterators to make many of the operations +specified using the identifiers a and b invalid for non-const +iterators. --25.2.8 [lib.alg.unique], paragraph 3: -
-See DR 239.
+Related issue: 477
+Proposed resolution:
--4) References to other DRs: -
+Remove the "r->m" line from the Forward Iterator requirements +table. Change
++ "const X" +--See DR 202, but which does not address any of the problems described in -this Defect Report [Note: This DR is supposed to complement DR 202]. -See DR 239. -See DR submitted by Thomas Mang regarding invalid iterator arithmetic -expressions. -
+to
--[1]: -The wording of these references is not always unambiguous, and provided -examples partially contradict verbal description of the algorithms, -because the verbal description resembles the problematic wording of -ISO/IEC 14882:2003. -
++ "X or const X" +--[2]: -Illustration of conforming implementations according to current wording: -
+in paragraph 11 of [lib.iterator.requirements].
--One way the author of this DR considers how this "elimination" could be -achieved by a conforming implementation according to current wording is -by substituting each r-element by _any_ s-element [Note: s...stay; any -non-r-element], since all r-elements are "eliminated". -
--In case of a sequence consisting of elements being all 'equal' [Note: -See DR 202], substituting each r-element by the single s-element is the -only possible solution according to current wording. -
-Proposed resolution:
--
-491. std::list<>::unique incorrectly specified
Section: 23.2.2.4 [lib.list.ops] Status: New Submitter: Thomas Mang Date: 12 Dec 2004
-In Section 23.2.2.4 [lib.list.ops], paragraphs 19 to 21 describe the -behavior of the std::list<T, Allocator>::unique operation. However, the -current wording is defective for various reasons.
+479. Container requirements and placement new
Section: 23.1 [lib.container.requirements] Status: Open Submitter: Herb Sutter Date: 1 Aug 2004
+Nothing in the standard appears to make this program ill-formed:
+struct C { + void* operator new( size_t s ) { return ::operator new( s ); } + // NOTE: this hides in-place and nothrow new + }; + int main() { + vector<C> v; + v.push_back( C() ); + } +--1) Analysis of current wording: -
+Is that intentional? We should clarify whether or not we intended + to require containers to support types that define their own special + versions of operator new.
-23.2.2.4 [lib.list.ops], paragraph 19:
++Lillehammer: A container will definitely never use this overridden +operator new, but whether it will fail to compile is unclear from the +standard. Are containers supposed to use qualified or unqualified +placement new? 20.4.1.1 is somewhat relevant, but the standard +doesn't make it completely clear whether containers have to use +Allocator::construct(). If containers don't use it, the details of how +containers use placement new are unspecified. That is the real bug, +but it needs to be fixed as part of the allocator overhaul. Weak +support that the eventual solution should make this code well formed. + --Current wording says: -"Effects: Eliminates all but the first element from every consecutive -group of equal elements referred to by the iterator i in the range -[first + 1, last) for which *i == *(i - 1) (for the version of unique -with no argument) or pred(*i, *(i -1)) (for the version of unique with a -predicate argument) holds."
+Proposed resolution:
+
+482. Swapping pairs
Section: 20.2.2 [lib.pairs], 25.2.2 [lib.alg.swap] Status: Open Submitter: Andrew Koenig Date: 14 Sep 2004
+(Based on recent comp.std.c++ discussion)
--This sentences makes use of the undefined term "Eliminates". Although it -is, to a certain degree, reasonable to consider the term "eliminate" -synonymous with "erase", using "Erase" in the first place, as the -wording of 23.2.2.4 [lib.list.ops], paragraph 15 does, would be clearer.
+Pair (and tuple) should specialize std::swap to work in terms of +std::swap on their components. For example, there's no obvious reason +why swapping two objects of type pair<vector<int>, +list<double> > should not take O(1).
+Proposed resolution:
--The range of the elements referred to by iterator i is "[first + 1, -last)". However, neither "first" nor "last" is defined.
--The sentence makes three times use of iterator arithmetic expressions ( -"first + 1", "*i == *(i - 1)", "pred(*i, *(i -1))" ) which is not -defined for bidirectional iterator [see DR submitted by Thomas Mang -regarding invalid iterator arithmetic expressions].
+[Lillehammer: We agree it should be swappable. Howard will + provide wording.]
--The same problems as pointed out in DR 202 (equivalence relation / order -of arguments for pred()) apply to this paragraph.
+
+484. Convertible to T
Section: 24.1.1 [lib.input.iterators] Status: Open Submitter: Chris Date: 16 Sep 2004
+From comp.std.c++:
-23.2.2.4 [lib.list.ops], paragraph 20: +I note that given an input iterator a for type T, +then *a only has to be "convertable to T", not actually of type T.
--Current wording says: -"Throws: Nothing unless an exception in thrown by *i == *(i-1) or -pred(*i, *(i - 1))"
+Firstly, I can't seem to find an exact definition of "convertable to T". +While I assume it is the obvious definition (an implicit conversion), I +can't find an exact definition. Is there one?
--The sentence makes two times use of invalid iterator arithmetic -expressions ( "*i == *(i - 1)", "pred(*i, *(i -1))" ). -
--[Note: Minor typos: "in" / missing dot at end of sentence.] -
+Slightly more worryingly, there doesn't seem to be any restriction on +the this type, other than it is "convertable to T". Consider two input +iterators a and b. I would personally assume that most people would +expect *a==*b would perform T(*a)==T(*b), however it doesn't seem that +the standard requires that, and that whatever type *a is (call it U) +could have == defined on it with totally different symantics and still +be a valid inputer iterator.
--23.2.2.4 [lib.list.ops], paragraph 21:
+Is this a correct reading? When using input iterators should I write +T(*a) all over the place to be sure that the object i'm using is the +class I expect?
--Current wording says: -"Complexity: If the range (last - first) is not empty, exactly (last - -first) - 1 applications of the corresponding predicate, otherwise no -application of the predicate.
+This is especially a nuisance for operations that are defined to be + "convertible to bool". (This is probably allowed so that + implementations could return say an int and avoid an unnessary + conversion. However all implementations I have seen simply return a + bool anyway. Typical implemtations of STL algorithms just write + things like while(a!=b && *a!=0). But strictly + speaking, there are lots of types that are convertible to T but + that also overload the appropriate operators so this doesn't behave + as expected.
--See DR 315 regarding "(last - first)" not yielding a range.
+If we want to make code like this legal (which most people seem to + expect), then we'll need to tighten up what we mean by "convertible + to T".
+Proposed resolution:
+[Lillehammer: The first part is NAD, since "convertible" is + well-defined in core. The second part is basically about pathological + overloads. It's a minor problem but a real one. So leave open for + now, hope we solve it as part of iterator redesign.]
+
+485. output iterator insufficently constrained
Section: 24.1.2 [lib.output.iterators] Status: Open Submitter: Chris Date: 13 Oct 2004
-Invalid iterator arithmetic expression "(last - first) - 1" left .
+The note on 24.1.2 Output iterators insufficently limits what can be +performed on output iterators. While it requires that each iterator is +progressed through only once and that each iterator is written to only +once, it does not require the following things: +Note: Here it is assumed that x is an output iterator of type X which +has not yet been assigned to.
-2) Description of intended behavior:
+a) That each value of the output iterator is written to: +The standard allows: +++x; ++x; ++x; +
-For the rest of this Defect Report, it is assumed that "eliminate" is -supposed to be synonymous to "erase", that "first" is equivalent to an -iterator obtained by a call to begin(), "last" is equivalent to an -iterator obtained by a call to end(), and that all invalid iterator -arithmetic expressions are resolved as described in DR submitted by -Thomas Mang regarding invalid iterator arithmetic expressions.
+b) That assignments to the output iterator are made in order +X a(x); ++a; *a=1; *x=2; is allowed +-Furthermore, the resolutions of DR 202 are considered regarding -equivalence relation and order of arguments for a call to pred.
+c) Chains of output iterators cannot be constructed: +X a(x); ++a; X b(a); ++b; X c(b); ++c; is allowed, and under the current +wording (I believe) x,a,b,c could be written to in any order. + +I do not believe this was the intension of the standard?
+Proposed resolution:
+[Lillehammer: Real issue. There are lots of constraints we + intended but didn't specify. Should be solved as part of iterator + redesign.]
+
+488. rotate throws away useful information
Section: 25.2.10 [lib.alg.rotate] Status: Open Submitter: Howard Hinnant Date: 22 Nov 2004
-All implementations known to the author of this Defect Report comply -with these assumptions, apart from the impact of the alternative -resolution of DR 202. Except for the changes implied by the resolutions -of DR 202, no impact on current code is expected.
+rotate takes 3 iterators: first, middle and last which point into a +sequence, and rearranges the sequence such that the subrange [middle, +last) is now at the beginning of the sequence and the subrange [first, +middle) follows. The return type is void. +-3) Proposed fixes:
+In many use cases of rotate, the client needs to know where the +subrange [first, middle) starts after the rotate is performed. This +might look like: + +rotate(first, middle, last); + Iterator i = advance(first, distance(middle, last)); +-Change 23.2.2.4 [lib.list.ops], paragraph 19 to:
+Unless the iterators are random access, the computation to find the +start of the subrange [first, middle) has linear complexity. However, +it is not difficult for rotate to return this information with +negligible additional computation expense. So the client could code: + +Iterator i = rotate(first, middle, last); +-"Effect: Erases all but the first element from every consecutive group -of elements, referred to by the iterator i in the range [begin(), -end()), for which the following conditions hold: *(i-1) == *i (for the -version of unique with no argument) or pred(*(i-1), *i) != false (for -the version of unique with a predicate argument)."
+and the resulting program becomes significantly more efficient. +-Comments to the new wording:
+While the backwards compatibility hit with this change is not zero, it +is very small (similar to that of lwg 130), and there is +a significant benefit to the change. + --a) The new wording was influenced by DR 202 and the resolutions -presented there. If DR 202 is resolved in another way, the proposed -wording need also additional review. -b) "Erases" refers in the author's opinion unambiguously to the member -function "erase". In case there is doubt this might not be unamgibuous, -a direct reference to the member function "erase" is suggested [Note: -This would also imply a change of 23.2.2.4 [lib.list.ops], paragraph -15.]. -c) The expression "(i - 1)" was left, but is expected that DR submitted -by Thomas Mang regarding invalid iterator arithmetic expressions will -take this into account. -d) The wording "(for the version of unique with no argument)" and "(for -the version of unique with a predicate argument)" was kept consciously -for clarity. -e) "begin()" substitutes "first", and "end()" substitutes "last". The -range need adjustment from "[first + 1, last)" to "[begin(), end())" to -ensure a valid range in case of an empty list. -f) If it is considered that the wording is unclear whether it declares -the element of a group which consists of only a single element -implicitly to be the first element of this group [Note: Such an -interpretation could eventually arise especially in case size() == 1] , -the following additional sentence is proposed: "If such a group of -elements consists of only a single element, this element is also -considered the first element."
+Proposed resolution:
+In 25p2, change:
+template<class ForwardIterator> + void rotate(ForwardIterator first, ForwardIterator middle, + ForwardIterator last); +--Change 23.2.2.4 [lib.list.ops], paragraph 20 to:
+to:
--"Throws: Nothing unless an exception is thrown by *(i-1) == *i or -pred(*(i-1), *i)."
+template<class ForwardIterator> + ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, + ForwardIterator last); +--Comments to the new wording:
+In 25.2.10, change:
--a) The wording regarding the conditions is identical to proposed -23.2.2.4 [lib.list.ops], paragraph 19. If 23.2.2.4 [lib.list.ops], -paragraph 19 is resolved in another way, the proposed wording need also -additional review. -b) The expression "(i - 1)" was left, but is expected that DR submitted -by Thomas Mang regarding invalid iterator arithmetic expressions will -take this into account. -c) Typos fixed.
+template<class ForwardIterator> + void rotate(ForwardIterator first, ForwardIterator middle, + ForwardIterator last); +--Change 23.2.2.4 [lib.list.ops], paragraph 21 to:
+to:
--"Complexity: If empty() == false, exactly size() - 1 applications of the -corresponding predicate, otherwise no applications of the corresponding -predicate."
+template<class ForwardIterator> + ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, + ForwardIterator last); +--Comments to the new wording:
+In 25.2.10 insert a new paragraph after p1:
--a) The new wording is supposed to also replace the proposed resolution -of DR 315, which suffers from the problem of undefined "first" / "last". -
++-Returns: first + (last - middle).
+-5) References to other DRs:
+[ +The LWG agrees with this idea, but has one quibble: we want to make +sure not to give the impression that the function "advance" is +actually called, just that the nth iterator is returned. (Calling +advance is observable behavior, since users can specialize it for +their own iterators.) Howard will provide wording. +]
-See DR 202. -See DR 239. -See DR 315. -See DR submitted by Thomas Mang regarding invalid iterator arithmetic -expressions.
+[Howard provided wording for mid-meeting-mailing Jun. 2005.]
-Proposed resolution:
--
-492. Invalid iterator arithmetic expressions
Section: 23 [lib.containers], 24 [lib.iterators], 25 [lib.algorithms] Status: New Submitter: Thomas Mang Date: 12 Dec 2004
+492. Invalid iterator arithmetic expressions
Section: 23 [lib.containers], 24 [lib.iterators], 25 [lib.algorithms] Status: Open Submitter: Thomas Mang Date: 12 Dec 2004
Various clauses other than clause 25 make use of iterator arithmetic not supported by the iterator category in question. Algorithms in clause 25 are exceptional because of 25 [lib.algorithms], @@ -6923,78 +4472,14 @@ See DR 237. The resolution could then also read "Linear in last - first".
Proposed resolution:
--
-
-493. Undefined Expression in Input Iterator Note Title
Section: 24.1.1 [lib.input.iterators] Status: New Submitter: Chris Jefferson Date: 13 Dec 2004
-1) In 24.1.1/3, the following text is currently present.
- -"Note: For input iterators, a==b does not imply ++a=++b (Equality does -not guarantee the substitution property or referential transparency)."
- -However, when in Table 72, part of the definition of ++r is given as:
- -"pre: r is dereferenceable. -post: any copies of the previous value of r are no longer required -either to be dereferenceable ..."
-While a==b does not imply that b is a copy of a, this statement should -perhaps still be made more clear.
+[Lillehammer: Minor issue, but real. We have a blanket statement +about this in 25/11. But (a) it should be in 17, not 25; and (b) it's +not quite broad enough, because there are some arithmetic expressions +it doesn't cover. Bill will provide wording.]
-2) There are no changes to intended behaviour
- --3) This Note should be altered to say "Note: For input iterators a==b, -when its behaviour is defined ++a==++b may still be false (Equality does -not guarantee the substitution property or referential transparency).
- -Proposed resolution:
--
-
-494. Wrong runtime complexity for associative container's insert and delete
Section: 23.1.2 [lib.associative.reqmts] Status: New Submitter: Hans B os Date: 19 Dec 2004
-According to [lib.associative.reqmts] table 69, the runtime comlexity -of insert(p, t) and erase(q) can be done in amortized constant time.
- -It was my understanding that an associative container could be -implemented as a balanced binary tree.
- -For inser(p, t), you 'll have to iterate to p's next node to see if t -can be placed next to p. Furthermore, the insertion usually takes -place at leaf nodes. An insert next to the root node will be done at -the left of the root next node
- -So when p is the root node you 'll have to iterate from the root to -its next node, which takes O(log(size)) time in a balanced tree.
- -If you insert all values with insert(root, t) (where root is the -root of the tree before insertion) then each insert takes O(log(size)) -time. The amortized complexity per insertion will be O(log(size)) -also.
- -For erase(q), the normal algorithm for deleting a node that has no -empty left or right subtree, is to iterate to the next (or previous), -which is a leaf node. Then exchange the node with the next and delete -the leaf node. Furthermore according to DR 130, erase should return -the next node of the node erased. Thus erasing the root node, -requires iterating to the next node.
- -Now if you empty a map by deleting the root node until the map is -empty, each operation will take O(log(size)), and the amortized -complexity is still O(log(size)).
- -The operations can be done in amortized constant time if iterating -to the next node can be done in (non amortized) constant time. This -can be done by putting all nodes in a double linked list. This -requires two extra links per node. To me this is a bit overkill since -you can already efficiently insert or erase ranges with erase(first, -last) and insert(first, last).
- -Proposed resolution:
--
-495. Clause 22 template parameter requirements
Section: 22 [lib.localization] Status: New Submitter: Beman Dawes Date: 10 Jan 2005
+495. Clause 22 template parameter requirements
Section: 22 [lib.localization] Status: Review Submitter: Beman Dawes Date: 10 Jan 2005
It appears that there are no requirements specified for many of the template parameters in clause 22. It looks like this issue has never come up, except perhaps for Facet.
@@ -7028,8 +4513,36 @@ text identifies the requirements for the name International but not for Intl.Proposed resolution:
+Change 17.3.2.1 [lib.type.descriptions], paragraph 1, from:
++The Requirements subclauses may describe names that are used to +specify constraints on template arguments.153) These names are used in +clauses 20, 23, 25, and 26 to describe the types that may be supplied +as arguments by a C++ program when instantiating template components +from the library. ++to:
++The Requirements subclauses may describe names that are used to +specify constraints on template arguments.153) These names are used in +library clauses to describe the types that may be supplied as +arguments by a C++ program when instantiating template components from +the library. ++ +In the front matter of class 22, locales, add:
++Template parameter types internT and externT shall meet the +requirements of charT (described in 21 [lib.strings]). ++Rationale:
++ Again, a blanket clause isn't blanket enough. Also, we've got a + couple of names that we don't have blanket requirement statements + for. The only issue is what to do about stateT. This wording is + thin, but probably adequate.
-496. Illegal use of "T" in vector<bool>
Section: 23.2.5 [lib.vector.bool] Status: New Submitter: richard@ex-parrot.com Date: 10 Feb 2005
+496. Illegal use of "T" in vector<bool>
Section: 23.2.5 [lib.vector.bool] Status: Ready Submitter: richard@ex-parrot.com Date: 10 Feb 2005
In the synopsis of the std::vector<bool> specialisation in 23.2.5 [lib.vector.bool], the non-template assign() function has the signature
@@ -7037,9 +4550,341 @@ the non-template assign() function has the signaturevoid assign( size_type n, const T& t );+The type, T, is not defined in this context.
+Proposed resolution:
+Replace "T" with "value_type".
+
+497. meaning of numeric_limits::traps for floating point types
Section: 18.2.1.2 [lib.numeric.limits.members] Status: Review Submitter: Martin Sebor Date: 2 Mar 2005
+ +18.2.1.2, p59 says this much about the traps member of numeric_limits:
+ +++ +static const bool traps;
+
+-59- true if trapping is implemented for the type.204) +
+Footnote 204: Required by LIA-1. +It's not clear what is meant by "is implemented" here.
+ ++In the context of floating point numbers it seems reasonable to expect +to be able to use traps to determine whether a program can "safely" use +infinity(), quiet_NaN(), etc., in arithmetic expressions, that is +without causing a trap (i.e., on UNIX without having to worry about +getting a signal). When traps is true, I would expect any of the +operations in section 7 of IEEE 754 to cause a trap (and my program +to get a SIGFPE). So, for example, on Alpha, I would expect traps +to be true by default (unless I compiled my program with the -ieee +option), false by default on most other popular architectures, +including IA64, MIPS, PA-RISC, PPC, SPARC, and x86 which require +traps to be explicitly enabled by the program. +
+ ++Another possible interpretation of p59 is that traps should be true +on any implementation that supports traps regardless of whether they +are enabled by default or not. I don't think such an interpretation +makes the traps member very useful, even though that is how traps is +implemented on several platforms. It is also the only way to implement +traps on platforms that allow programs to enable and disable trapping +at runtime. +
+Proposed resolution:
+Change p59 to read:
+True if, at program startup, there exists a value of the type that + would cause an arithmetic operation using that value to trap.+Rationale:
++ Real issue, since trapping can be turned on and off. Unclear what a + static query can say about a dynamic issue. The real advice we should + give users is to use cfenv for these sorts of queries. But this new + proposed resolution is at least consistent and slightly better than + nothing.
+
+498. Requirements for partition() and stable_partition() too strong
Section: 25.2.12 [lib.alg.partitions] Status: New Submitter: Sean Parent, Joe Gottman Date: 4 May 2005
++Problem: +The iterator requirements for partition() and stable_partition() [25.2.12] +are listed as BidirectionalIterator, however, there are efficient algorithms +for these functions that only require ForwardIterator that have been known +since before the standard existed. The SGI implementation includes these (see +http://www.sgi.com/tech/stl/partition.html +and +http://www.sgi.com/tech/stl/stable_partition.html). +
+Proposed resolution:
++Change 25.2.12 from
++template<class BidirectionalIterator, class Predicate> +BidirectionalIterator partition(BidirectionalIterato r first, + BidirectionalIterator last, + Predicate pred); +to
++template<class ForwardIterator, class Predicate> +ForwardIterator partition(ForwardIterator first, + ForwardIterator last, + Predicate pred); +Change the complexity from
+ ++ ++At most (last - first)/2 swaps are done. Exactly (last - first) +applications of the predicate are done. +
to
+ ++ ++If ForwardIterator is a bidirectional_iterator, at most (last - first)/2 +swaps are done; otherwise at most (last - first) swaps are done. Exactly +(last - first) applications of the predicate are done. +
+499. Std. doesn't seem to require stable_sort() to be stable!
Section: 25.3.1.2 [lib.stable.sort] Status: New Submitter: Prateek Karandikar Date: 12 Apr 2005
+++ ++17.3.1.1 Summary
+ ++1 The Summary provides a synopsis of the category, and introduces the +first-level subclauses. Each subclause also provides a summary, listing +the headers specified in the subclause and the library entities +provided in each header. +
++2 Paragraphs labelled "Note(s):" or "Example(s):" are informative, +other paragraphs are normative. +
+So this means that a "Notes" paragraph wouldn't be normative.
+ +++ ++25.3.1.2 stable_sort +
+template<class RandomAccessIterator> +void stable_sort(RandomAccessIterat or first, RandomAccessIterator last); + +template<class RandomAccessIterator, class Compare> +void stable_sort(RandomAccessIterat or first, RandomAccessIterator last, Compare comp); +++1 Effects: Sorts the elements in the range [first, last). +
++2 Complexity: It does at most N(log N)^2 (where N == last - first) +comparisons; if enough extra memory is available, it is N log N. +
++3 Notes: Stable: the relative order of the equivalent elements is +preserved. +
++The Notes para is informative, and nowhere else is stability mentioned above. +
+ ++Also, I just searched for the word "stable" in my copy of the Standard. +and the phrase "Notes: Stable: the relative order of the elements..." +is repeated several times in the Standard library clauses for +describing various functions. How is it that stability is talked about +in the informative paragraph? Or am I missing something obvious? +
+Proposed resolution:
++
+
+500. do_length cannot be implemented correctly
Section: 22.2.1.5.2 [lib.locale.codecvt.virtuals] Status: New Submitter: Krzysztof ¯elechowski Date: 24 May 2005
++
+- codecvt::do_length is of type int;
+- it is assumed to be sort-of returning from_next - from of type ptrdiff_t;
+- ptrdiff_t cannot be cast to an int without data loss.
++Contradiction. +
+Proposed resolution:
++
+
+501. Proposal: strengthen guarantees of lib.comparisons
Section: 20.3.3 [lib.comparisons] Status: New Submitter: Me <anti_spam_email2003@yahoo.com> Date: 7 Jun 2005
++"For templates greater, less, greater_equal, and less_equal, +the specializations for any pointer type yield a total order, even if +the built-in operators <, >, <=, >= do not." ++ ++The standard should do much better than guarantee that these provide a +total order, it should guarantee that it can be used to test if memory +overlaps, i.e. write a portable memmove. You can imagine a platform +where the built-in operators use a uint32_t comparison (this tests for +overlap on this platform) but the less<T*> functor is allowed to be +defined to use a int32_t comparison. On this platform, if you use +std::less with the intent of making a portable memmove, comparison on +an array that straddles the 0x7FFFFFFF/0x8000000 boundary can give +incorrect results. +
+Proposed resolution:
++Add a footnote to 20.3.3/8 saying: +
+ ++Given a p1 and p2 such that p1 points to N objects of type T and p2 +points to M objects of type T. If [p1,p1+N) does not overlap [p2,p2+M), +less returns the same value when comparing all pointers in [p1,p1+N) to +all pointers in [p2,p2+M). Otherwise, there is a value Q and a value R +such that less returns the same value when comparing all pointers in +[p1,p1+Q) to all pointers in [p2,p2+R) and an opposite value when +comparing all pointers in [p1+Q,p1+N) to all pointers in [p2+R,p2+M). +For the sake of completeness, the null pointer value (4.10) for T is +considered to be an array of 1 object that doesn't overlap with any +non-null pointer to T. less_equal, greater, greater_equal, equal_to, +and not_equal_to give the expected results based on the total ordering +semantics of less. For T of void, treat it as having similar semantics +as T of char i.e. less<cv T*>(a, b) gives the same results as less<cv +void*>(a, b) which gives the same results as less<cv char*>((cv +char*)(cv void*)a, (cv char*)(cv void*)b). ++ ++I'm also thinking there should be a footnote to 20.3.3/1 saying that if +A and B are similar types (4.4/4), comp<A>(a,b) returns the same value +as comp<B>(a,b) (where comp is less, less_equal, etc.). But this might +be problematic if there is some really funky operator overloading going +on that does different things based on cv (that should be undefined +behavior if somebody does that though). This at least should be +guaranteed for all POD types (especially pointers) that use the +built-in comparison operators. +
+ +
+502. Proposition: Clarification of the interaction between a facet and an iterator
Section: 22.1.1.1.1 [lib.locale.category] Status: New Submitter: Christopher Conrade Zseleghovski Date: 7 Jun 2005
++Motivation: +
+ ++This requirement seems obvious to me, it is the essence of code modularity. +I have complained to Mr. Plauger that the Dinkumware library does not +observe this principle but he objected that this behaviour is not covered in +the standard. +
+Proposed resolution:
++Append the following point to 22.1.1.1.1: +
+ ++6. The implementation of a facet of Table 52 parametrized with an +InputIterator/OutputIterator should use that iterator only as character +source/sink respectively. +For a *_get facet, it means that the value received depends only on the +sequence of input characters and not on how they are accessed. +For a *_put facet, it means that the sequence of characters output depends +only on the value to be formatted and not of how the characters are stored. +
+
+503. more on locales
Section: 22.2 [lib.locale.categories] Status: New Submitter: P.J. Plauger Date: 20 Jun 2005
++a) In 22.2.1.1 para. 2 we refer to "the instantiations required in Table +51" to refer to the facet *objects* associated with a locale. And we +almost certainly mean just those associated with the default or "C" +locale. Otherwise, you can't switch to a locale that enforces a different +mapping between narrow and wide characters, or that defines additional +uppercase characters. +
+ ++b) 22.2.1.5 para. 3 (codecvt) has the same issues. +
+ ++c) 22.2.1.5.2 (do_unshift) is even worse. It *forbids* the generation of +a homing sequence for the basic character set, which might very well need +one. +
+ ++d) 22.2.1.5.2 (do_length) likewise dictates that the default mapping +between wide and narrow characters be taken as one-for-one. +
+ ++e) 22.2.2 para. 2 (num_get/put) is both muddled and vacuous, as far as +I can tell. The muddle is, as before, calling Table 51 a list of +instantiations. But the constraint it applies seems to me to cover +*all* defined uses of num_get/put, so why bother to say so? +
+ ++f) 22.2.3.1.2 para. 1(do_decimal_point) says "The required instantiations +return '.' or L'.'.) Presumably this means "as appropriate for the +character type. But given the vague definition of "required" earlier, +this overrules *any* change of decimal point for non "C" locales. +Surely we don't want to do that. +
+ ++g) 22.2.3.1.2 para. 2 (do_thousands_sep) says "The required instantiations +return ',' or L','.) As above, this probably means "as appropriate for the +character type. But this overrules the "C" locale, which requires *no* +character ('\0') for the thousands separator. Even if we agree that we +don't mean to block changes in decimal point or thousands separator, +we should also eliminate this clear incompatibility with C. +
+ ++h) 22.2.3.1.2 para. 2 (do_grouping) says "The required instantiations +return the empty string, indicating no grouping." Same considerations +as for do_decimal_point. +
+ ++i) 22.2.4.1 para. 1 (collate) refers to "instantiations required in Table +51". Same bad jargon. +
+-The type, T, is not defined in this context and should be replaced by -bool or value_type.
+j) 22.2.4.1.2 para. 1 (do_compare) refers to "instantiations required +in Table 51". Same bad jargon. + + ++k) 22.2.5 para. 1 (time_get/put) uses the same muddled and vacuous +as num_get/put. +
+ ++l) 22.2.6 para. 2 (money_get/put) uses the same muddled and vacuous +as num_get/put. +
+ ++m) 22.2.6.3.2 (do_pos/neg_format) says "The instantiations required +in Table 51 ... return an object of type pattern initialized to +{symbol, sign, none, value}." This once again *overrides* the "C" +locale, as well as any other locale." +
+ ++3) We constrain the use_facet calls that can be made by num_get/put, +so why don't we do the same for money_get/put? Or for any of the +other facets, for that matter? +
+ ++4) As an almost aside, we spell out when a facet needs to use the ctype +facet, but several also need to use a codecvt facet and we don't say so. +
Proposed resolution:
diff --git a/libstdc++-v3/docs/html/ext/lwg-defects.html b/libstdc++-v3/docs/html/ext/lwg-defects.html index 1dd18551422..f7ff410c01d 100644 --- a/libstdc++-v3/docs/html/ext/lwg-defects.html +++ b/libstdc++-v3/docs/html/ext/lwg-defects.html @@ -5,11 +5,11 @@
Doc. no. | -N1763=05-0023 | +N1831=05-0091 |
Date: | -2005-03-04 | +2005-06-24 |
Project: | @@ -17,10 +17,10 @@||
Reply to: | -Matt Austern <austern@google.com> | +Howard Hinnant <howard.hinnant@gmail.com> |
Reference ISO/IEC IS 14882:1998(E)
Also see:
See 99-0040/N1216, October 22, 1999, by Stephen D. Clamage for the analysis supporting to the proposed resolution.
Section: 23.3.5 [lib.template.bitset] Status: TC Submitter: Matt Austern Date: 22 Jan 1998
+Section: 23.3.5 [lib.template.bitset] Status: TC Submitter: Matt Austern Date: 22 Jan 1998
(1) bitset<>::operator[] is mentioned in the class synopsis (23.3.5), but it is not documented in 23.3.5.2.
@@ -671,7 +680,7 @@ it's undefined.In 27.6.1.2.3 [lib.istream::extractors], replace "eos" with "charT()"
Section: 22.1.1.3 [lib.locale.members] Status: TC Submitter: Nathan Myers Date: 6 Aug 1998
+Section: 22.1.1.3 [lib.locale.members] Status: TC Submitter: Nathan Myers Date: 6 Aug 1998
locale::combine is the only member function of locale (other than constructors and destructor) that is not const. There is no reason for it not to be const, and good reasons why it should have been const. Furthermore, leaving it non-const conflicts with 22.1.1 @@ -880,7 +889,7 @@ and do_out".
"do_convert" to "do_in or do_out". Also, in 22.2.1.5.2 [lib.locale.codecvt.virtuals], change "do_convert()" to "do_in or do_out".Section: 21.3.7.9 [lib.string.io] Status: TC Submitter: Nathan Myers Date: 6 Aug 1998
+Section: 21.3.7.9 [lib.string.io] Status: TC Submitter: Nathan Myers Date: 6 Aug 1998
In the description of operator<< applied to strings, the standard says that uses the smaller of os.width() and str.size(), to pad "as described in stage 3" elsewhere; but this is inconsistent, as this allows no possibility of space for padding.
@@ -1200,7 +1209,7 @@ initialization/identification system depends...", or (at the editor's option) replace it with a place-holder to keep the paragraph numbering the same.Section: 27.4.2 [lib.ios.base] Status: TC Submitter: Nathan Myers Date: 6 Aug 1998
+Section: 27.4.2 [lib.ios.base] Status: TC Submitter: Nathan Myers Date: 6 Aug 1998
The description of ios_base::iword() and pword() in 27.4.2.4 [lib.ios.members.static], say that if they fail, they "set badbit, which may throw an exception". However, ios_base offers no interface to set or to test badbit; those interfaces are defined in @@ -1662,8 +1671,7 @@ character c by
for any sequences of characters; and the effect of pushing back a character c by
-- ungetc(c, f); +return 0; }ungetc(c, f);is the same as the effect of
@@ -2360,7 +2368,7 @@ item from: extracted.
-69. Must elements of a vector be contiguous?
Section: 23.2.4 [lib.vector] Status: TC Submitter: Andrew Koenig Date: 29 Jul 1998
+69. Must elements of a vector be contiguous?
Section: 23.2.4 [lib.vector] Status: TC Submitter: Andrew Koenig Date: 29 Jul 1998
The issue is this: Must the elements of a vector be in contiguous memory?
(Please note that this is entirely separate from the question of @@ -2604,7 +2612,7 @@ return value.]
to:
template<class T> complex<T> polar(const T& rho, const T& theta = 0);
-80. Global Operators of complex declared twice
Section: 26.2.1 [lib.complex.synopsis], 26.2.2 [lib.complex] Status: TC Submitter: Nico Josuttis Date: 29 Sep 1998
+80. Global Operators of complex declared twice
Section: 26.2.1 [lib.complex.synopsis], 26.2.2 [lib.complex] Status: TC Submitter: Nico Josuttis Date: 29 Sep 1998
Both 26.2.1 and 26.2.2 contain declarations of global operators for class complex. This redundancy should be removed.
Proposed resolution:
@@ -2861,7 +2869,7 @@ for *r++ from T to "convertible to T". of input iterators, we can't impose any requirements in the Input Iterator requirements table that forward iterators don't satisfy.
-103. set::iterator is required to be modifiable, but this allows modification of keys
Section: 23.1.2 [lib.associative.reqmts] Status: WP Submitter: AFNOR Date: 7 Oct 1998
+103. set::iterator is required to be modifiable, but this allows modification of keys
Section: 23.1.2 [lib.associative.reqmts] Status: WP Submitter: AFNOR Date: 7 Oct 1998
Set::iterator is described as implementation-defined with a reference to the container requirement; the container requirement says that const_iterator is an iterator pointing to const T and iterator an @@ -3132,7 +3140,7 @@ replace:
bool equal(const istreambuf_iterator& b) const;
-112. Minor typo in ostreambuf_iterator constructor
Section: 24.5.4.1 [lib.ostreambuf.iter.cons] Status: TC Submitter: Matt Austern Date: 20 Oct 1998
+112. Minor typo in ostreambuf_iterator constructor
Section: 24.5.4.1 [lib.ostreambuf.iter.cons] Status: TC Submitter: Matt Austern Date: 20 Oct 1998
The requires clause for ostreambuf_iterator's constructor from an ostream_type (24.5.4.1, paragraph 1) reads "s is not null". However, s is a @@ -3150,7 +3158,7 @@ reading:
Requires: s.rdbuf() is not null.
-114. Placement forms example in error twice
Section: 18.4.1.3 [lib.new.delete.placement] Status: TC Submitter: Steve Clamage Date: 28 Oct 1998
+114. Placement forms example in error twice
Section: 18.4.1.3 [lib.new.delete.placement] Status: TC Submitter: Steve Clamage Date: 28 Oct 1998
Section 18.4.1.3 contains the following example:
[Example: This can be useful for constructing an object at a known address: @@ -3359,7 +3367,7 @@ operator>>(int& val);[Post-Tokyo: PJP provided the above wording.]
-119. Should virtual functions be allowed to strengthen the exception specification?
Section: 17.4.4.8 [lib.res.on.exception.handling] Status: TC Submitter: Judy Ward Date: 15 Dec 1998
+119. Should virtual functions be allowed to strengthen the exception specification?
Section: 17.4.4.8 [lib.res.on.exception.handling] Status: TC Submitter: Judy Ward Date: 15 Dec 1998
Section 17.4.4.8 [lib.res.on.exception.handling] states:
"An implementation may strengthen the exception-specification @@ -3753,6 +3761,65 @@ stream state in case of failure.
Rationale:
Setting failbit is the usual error reporting mechanism for streams
+
+130. Return type of container::erase(iterator) differs for associative containers
Section: 23.1.2 [lib.associative.reqmts], 23.1.1 [lib.sequence.reqmts] Status: DR Submitter: Andrew Koenig Date: 2 Mar 1999
+Table 67 (23.1.1) says that container::erase(iterator) returns an +iterator. Table 69 (23.1.2) says that in addition to this requirement, +associative containers also say that container::erase(iterator) +returns void. That's not an addition; it's a change to the +requirements, which has the effect of making associative containers +fail to meet the requirements for containers.
+Proposed resolution:
+ ++In 23.1.2 [lib.associative.reqmts], in Table 69 Associative container +requirements, change the return type of a.erase(q) from +void to iterator. Change the +assertion/not/pre/post-condition from "erases the element pointed to +by q" to "erases the element pointed to by q. +Returns an iterator pointing to the element immediately following q +prior to the element being erased. If no such element exists, a.end() +is returned." +
+ ++In 23.1.2 [lib.associative.reqmts], in Table 69 Associative container +requirements, change the return type of a.erase(q1, q2) +from void to iterator. Change the +assertion/not/pre/post-condition from "erases the elements in the +range [q1, q2)" to "erases the elements in the range [q1, +q2). Returns q2." +
+ ++In 23.3.1 [lib.map], in the map class synopsis; and +in 23.3.2 [lib.multimap], in the multimap class synopsis; and +in 23.3.3 [lib.set], in the set class synopsis; and +in 23.3.4 [lib.multiset], in the multiset class synopsis: +change the signature of the first erase overload to +
+iterator erase(iterator position); ++and change the signature of the third erase overload to
+iterator erase(iterator first, iterator last); ++ + +[Pre-Kona: reopened at the request of Howard Hinnant]
+ +[Post-Kona: the LWG agrees the return type should be +iterator, not void. (Alex Stepanov agrees too.) +Matt provided wording.]
+ +[ + Sydney: the proposed wording went in the right direction, but it + wasn't good enough. We want to return an iterator from the range form + of erase as well as the single-iterator form. Also, the wording is + slightly different from the wording we have for sequences; there's no + good reason for having a difference. Matt provided new wording, + which we will review at the next meeting. +]
+
132. list::resize description uses random access iterators
Section: 23.2.2.2 [lib.list.capacity] Status: TC Submitter: Howard Hinnant Date: 6 Mar 1999
The description reads:
@@ -4084,7 +4151,7 @@ follows an "all-or-none" rule.For inserters, the LWG believes there is no defect; the standard is correct as written.
-147. Library Intro refers to global functions that aren't global
Section: 17.4.4.3 [lib.global.functions] Status: TC Submitter: Lois Goldthwaite Date: 4 Jun 1999
+147. Library Intro refers to global functions that aren't global
Section: 17.4.4.3 [lib.global.functions] Status: TC Submitter: Lois Goldthwaite Date: 4 Jun 1999
The library had many global functions until 17.4.1.1 [lib.contents] paragraph 2 was added:
@@ -4338,8 +4405,8 @@ be fixed to use sbumpc() instead. "supplied" with the words "extracted from the stream".
-160. Typo: Use of non-existing function exception() -
Section: 27.6.1.1 [lib.istream] Status: TC Submitter: Dietmar Kühl Date: 20 Jul 1999
+160. Typo: Use of non-existing function exception() +
Section: 27.6.1.1 [lib.istream] Status: TC Submitter: Dietmar Kühl Date: 20 Jul 1999
The paragraph 4 refers to the function exception() which is not defined. Probably, the referred function is basic_ios<>::exceptions().
@@ -4500,7 +4567,7 @@ traits class for some arbitrary charT type, and we somehow have to deal with a const char*. There's nothing better to do but fall back to char_traits<char>
-168. Typo: formatted vs. unformatted
Section: 27.6.2.6 [lib.ostream.unformatted] Status: TC Submitter: Dietmar Kühl Date: 20 Jul 1999
+168. Typo: formatted vs. unformatted
Section: 27.6.2.6 [lib.ostream.unformatted] Status: TC Submitter: Dietmar Kühl Date: 20 Jul 1999
The first paragraph begins with a descriptions what has to be done in formatted output functions. Probably this is a typo and the paragraph really want to describe unformatted output functions...
@@ -5829,7 +5896,7 @@ change. or change the return to distance(b,a). The LWG preferred the former for consistency.
-211. operator>>(istream&, string&) doesn't set failbit
Section: 21.3.7.9 [lib.string.io] Status: TC Submitter: Scott Snyder Date: 4 Feb 2000
+211. operator>>(istream&, string&) doesn't set failbit
Section: 21.3.7.9 [lib.string.io] Status: TC Submitter: Scott Snyder Date: 4 Feb 2000
The description of the stream extraction operator for std::string (section 21.3.7.9 [lib.string.io]) does not contain a requirement that failbit be set in the case that the operator fails to extract any characters from the input @@ -5940,7 +6007,7 @@ declared above.
Section: 27.4.2.7 [lib.ios.base.cons] Status: TC Submitter: Jonathan Schilling, Howard Hinnant Date: 13 Mar 2000
+Section: 27.4.2.7 [lib.ios.base.cons] Status: TC Submitter: Jonathan Schilling, Howard Hinnant Date: 13 Mar 2000
The pre-conditions for the ios_base destructor are described in 27.4.2.7 paragraph 2:
@@ -7248,10 +7315,10 @@ iterators into *this, not into x.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 [lib.allocator.requirements] paragraph 4, the behavior of list when +>From 20.1.5 [lib.allocator.requirements] paragraph 4, the behavior of list when allocators compare nonequal is outside the scope of the standard.
-251. basic_stringbuf missing allocator_type
Section: 27.7.1 [lib.stringbuf] Status: WP Submitter: Martin Sebor Date: 28 Jul 2000
+251. basic_stringbuf missing allocator_type
Section: 27.7.1 [lib.stringbuf] Status: WP Submitter: Martin Sebor Date: 28 Jul 2000
The synopsis for the template class basic_stringbuf doesn't list a typedef for the template parameter Allocator. This makes it impossible to determine the type of @@ -7493,8 +7560,8 @@ In section 21.3.4, paragraph 1, change pos)".
-260. Inconsistent return type of istream_iterator::operator++(int) -
Section: 24.5.1.2 [lib.istream.iterator.ops] Status: WP Submitter: Martin Sebor Date: 27 Aug 2000
+260. Inconsistent return type of istream_iterator::operator++(int) +
Section: 24.5.1.2 [lib.istream.iterator.ops] Status: WP Submitter: Martin Sebor Date: 27 Aug 2000
The synopsis of istream_iterator::operator++(int) in 24.5.1 shows it as returning the iterator by value. 24.5.1.2, p5 shows the same operator as returning the iterator by reference. That's incorrect @@ -8955,7 +9022,7 @@ list" is excessively vague.]
[Post-Curaçao: Robert Klarer provided new wording.]
-301. basic_string template ctor effects clause omits allocator argument
Section: 21.3.1 [lib.string.cons] Status: WP Submitter: Martin Sebor Date: 27 Jan 2001
+301. basic_string template ctor effects clause omits allocator argument
Section: 21.3.1 [lib.string.cons] Status: WP Submitter: Martin Sebor Date: 27 Jan 2001
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 @@ -9506,7 +9573,7 @@ Table 82. However, <cstdio> is mentioned several times within section 27.8 [lib.file.streams], including 27.8.2 [lib.c.files].]
-310. Is errno a macro?
Section: 17.4.1.2 [lib.headers], 19.3 [lib.errno] Status: WP Submitter: Steve Clamage Date: 21 Mar 2001
+310. Is errno a macro?
Section: 17.4.1.2 [lib.headers], 19.3 [lib.errno] Status: WP Submitter: Steve Clamage Date: 21 Mar 2001
Exactly how should errno be declared in a conforming C++ header?
@@ -10449,7 +10516,7 @@ parameter name conveys real normative meaning.
338. is whitespace allowed between `-' and a digit?
Section: 22.2 [lib.locale.categories] Status: WP Submitter: Martin Sebor Date: 17 Sep 2001
-From Stage 2 processing in 22.2.2.1.2 [lib.facet.num.get.virtuals], p8 and 9 (the +>From Stage 2 processing in 22.2.2.1.2 [lib.facet.num.get.virtuals], p8 and 9 (the original text or the text corrected by the proposed resolution of issue 221) it seems clear that no whitespace is allowed within a number, but 22.2.3.1 [lib.locale.numpunct], p2, which gives the @@ -10506,7 +10573,7 @@ for it to differ gratuitously from the very specific description of numeric processing in 22.2.2.1.2 [lib.facet.num.get.virtuals]. The proposed resolution removes all mention of "whitespace" from that format.
-339. definition of bitmask type restricted to clause 27
Section: 22.2.1 [lib.category.ctype], 17.3.2.1.2 [lib.bitmask.types] Status: WP Submitter: Martin Sebor Date: 17 September 2001
+339. definition of bitmask type restricted to clause 27
Section: 22.2.1 [lib.category.ctype], 17.3.2.1.2 [lib.bitmask.types] Status: WP Submitter: Martin Sebor Date: 17 September 2001
The ctype_category::mask type is declared to be an enum in 22.2.1 [lib.category.ctype] with p1 then stating that it is a bitmask type, most likely referring to the definition of bitmask type in 17.3.2.1.2 [lib.bitmask.types], p1. However, the said definition only applies to @@ -10564,8 +10631,8 @@ following (note, in particluar, the cross-reference to 17.3.2.1.2 in consistent with the rest of the standard.]
-340. interpretation of has_facet<Facet>(loc) -
Section: 22.1.1.1.1 [lib.locale.category] Status: WP Submitter: Martin Sebor Date: 18 Sep 2001
+340. interpretation of has_facet<Facet>(loc) +
Section: 22.1.1.1.1 [lib.locale.category] Status: WP Submitter: Martin Sebor Date: 18 Sep 2001
It's unclear whether 22.1.1.1.1, p3 says that has_facet<Facet>(loc) returns true for any Facet @@ -11489,6 +11556,57 @@ Change the guarantee to "postcondition: r is dereferenceable."
Rationale:
Fixes an obvious typo
+386. Reverse iterator's operator[] has impossible return type
Section: 24.4.1.3.11 [lib.reverse.iter.opindex] Status: DR Submitter: Matt Austern Date: 23 Oct 2002
+In 24.4.1.3.11 [lib.reverse.iter.opindex], reverse_iterator<>::operator[] +is specified as having a return type of reverse_iterator::reference, +which is the same as iterator_traits<Iterator>::reference. +(Where Iterator is the underlying iterator type.)
+ +The trouble is that Iterator's own operator[] doesn't + necessarily have a return type + of iterator_traits<Iterator>::reference. Its + return type is merely required to be convertible + to Iterator's value type. The return type specified for + reverse_iterator's operator[] would thus appear to be impossible.
+ +With the resolution of issue 299, the type of + a[n] will continue to be required (for random access + iterators) to be convertible to the value type, and also a[n] = + t will be a valid expression. Implementations of + reverse_iterator will likely need to return a proxy from + operator[] to meet these requirements. As mentioned in the + comment from Dave Abrahams, the simplest way to specify that + reverse_iterator meet this requirement to just mandate + it and leave the return type of operator[] unspecified.
+ +Proposed resolution:
+ +In 24.4.1.2 [lib.reverse.iter.requirements] change:
+ +++ +reference operator[](difference_type n) const; ++to:
+ +++ + + + +unspecified operator[](difference_type n) const; // see lib.random.access.iterators ++[ +Comments from Dave Abrahams: IMO we should resolve 386 by just saying + that the return type of reverse_iterator's operator[] is + unspecified, allowing the random access iterator requirements to + impose an appropriate return type. If we accept 299's proposed + resolution (and I think we should), the return type will be + readable and writable, which is about as good as we can do. +]
+
389. Const overload of valarray::operator[] returns by value
Section: 26.3.2 [lib.template.valarray] Status: WP Submitter: Gabriel Dos Reis Date: 8 Nov 2002
Consider the following program:
#include <iostream> @@ -11772,7 +11890,7 @@ Providing this functionality would be difficult in some cases, and is believed to be of limited value.
-405. qsort and POD
Section: 25.4 [lib.alg.c.library] Status: DR Submitter: Ray Lischner Date: 08 Apr 2003
+405. qsort and POD
Section: 25.4 [lib.alg.c.library] Status: WP Submitter: Ray Lischner Date: 08 Apr 2003
Section 25.4 [lib.alg.c.library] describes bsearch and qsort, from the C standard library. Paragraph 4 does not list any restrictions on qsort, @@ -11790,6 +11908,29 @@ type."
[Something along these lines is clearly necessary. Matt provided wording.]
+
+406. vector::insert(s) exception safety
Section: 23.2.4.3 [lib.vector.modifiers] Status: DR Submitter: Dave Abrahams Date: 27 Apr 2003
++There is a possible defect in the standard: the standard text was +never intended to prevent arbitrary ForwardIterators, whose operations +may throw exceptions, from being passed, and it also wasn't intended +to require a temporary buffer in the case where ForwardIterators were +passed (and I think most implementations don't use one). As is, the +standard appears to impose requirements that aren't met by any +existing implementation. +
+Proposed resolution:
+Replace 23.2.4.3 [lib.vector.modifiers] paragraph 1 with:
++ 1- Notes: Causes reallocation if the new size is greater than the + old capacity. If no reallocation happens, all the iterators and + references before the insertion point remain valid. If an exception + is thrown other than by the copy constructor or assignment operator + of T or by any InputIterator operation there are no effects. ++ +[We probably need to say something similar for deque.]
+
407. Can singular iterators be destroyed?
Section: 24.1 [lib.iterator.requirements] Status: WP Submitter: Nathan Myers Date: 3 June 2003
@@ -11807,7 +11948,82 @@ destroying an iterator that holds a singular value, or the assignment of a non-singular value to an iterator that holds a singular value."
-410. Missing semantics for stack and queue comparison operators
Section: 23.2.3.1 [lib.queue], 23.2.3.3 [lib.stack] Status: DR Submitter: Hans Bos Date: 7 Jun 2003
+409. Closing an fstream should clear error state
Section: 27.8.1.7 [lib.ifstream.members], 27.8.1.10 [lib.ofstream.members] Status: DR Submitter: Nathan Myers Date: 3 June 2003
++A strict reading of 27.8.1 [lib.fstreams] shows that opening or +closing a basic_[io]fstream does not affect the error bits. This +means, for example, that if you read through a file up to EOF, and +then close the stream and reopen it at the beginning of the file, +the EOF bit in the stream's error state is still set. This is +counterintuitive. +
++The LWG considered this issue once before, as issue 22, +and put in a footnote to clarify that the strict reading was indeed +correct. We did that because we believed the standard was +unambiguous and consistent, and that we should not make architectural +changes in a TC. Now that we're working on a new revision of the +language, those considerations no longer apply. +
+Proposed resolution:
+ +Change 27.8.1.7 [lib.ifstream.members], para. 3 from:
+ ++Calls rdbuf()->open(s,mode|in). If that function returns a null +pointer, calls setstate(failbit) (which may throw ios_base::failure +[Footnote: (lib.iostate.flags)]. ++ +to:
+ +Calls rdbuf()->open(s,mode|in). If that function returns +a null pointer, calls setstate(failbit) (which may throw +ios_base::failure [Footnote: (lib.iostate.flags)), else calls clear(). ++ +Change 27.8.1.10 [lib.ofstream.members], para. 3 from:
+ +Calls rdbuf()->open(s,mode|out). If that function +returns a null pointer, calls setstate(failbit) (which may throw +ios_base::failure [Footnote: (lib.iostate.flags)). ++ +to:
+ +Calls rdbuf()->open(s,mode|out). If that function +returns a null pointer, calls setstate(failbit) (which may throw +ios_base::failure [Footnote: (lib.iostate.flags)), else calls clear(). ++ +Change 27.8.1.13 [lib.fstream.members], para. 3 from:
+ +Calls rdbuf()->open(s,mode), If that function returns a +null pointer, calls setstate(failbit), (which may throw +ios_base::failure). (lib.iostate.flags) ) ++ +to:
+ +Calls rdbuf()->open(s,mode), If that function returns a +null pointer, calls setstate(failbit), (which may throw +ios_base::failure). (lib.iostate.flags) ), else calls clear(). ++ + + +[Kona: the LWG agrees this is a good idea. Post-Kona: Bill +provided wording. He suggests having open, not close, clear the error +flags.]
+ +[Post-Sydney: Howard provided a new proposed resolution. The + old one didn't make sense because it proposed to fix this at the + level of basic_filebuf, which doesn't have access to the stream's + error state. Howard's proposed resolution fixes this at the level + of the three fstream class template instead.]
+ +
+410. Missing semantics for stack and queue comparison operators
Section: 23.2.3.1 [lib.queue], 23.2.3.3 [lib.stack] Status: WP Submitter: Hans Bos Date: 7 Jun 2003
Sections 23.2.3.1 [lib.queue] and 23.2.3.3 [lib.stack] list comparison operators (==, !=, <, <=, >, =>) for queue and @@ -11892,7 +12108,7 @@ set_intersection(), not union() and intersection().
Proposed resolution:
Change that sentence to use the correct names.
-412. Typo in 27.4.4.3
Section: 27.4.4.3 [lib.iostate.flags] Status: DR Submitter: Martin Sebor Date: 10 Jul 2003
+412. Typo in 27.4.4.3
Section: 27.4.4.3 [lib.iostate.flags] Status: WP Submitter: Martin Sebor Date: 10 Jul 2003
The Effects clause in 27.4.4.3 [lib.iostate.flags] paragraph 5 says that the function only throws if the respective bits are already set prior to @@ -11913,6 +12129,51 @@ exceptions()) == 0" with "If ((state | (rdbuf() ? goodbit : badbit)) setting the new state, or rdsate() after setting it. We intend the latter, of course. Post-Kona: Martin provided wording.]
+
+413. Proposed resolution to LDR#64 still wrong
Section: 27.6.1.2.3 [lib.istream::extractors] Status: DR Submitter: Bo Persson Date: 13 Jul 2003
++The second sentence of the proposed resolution says: +
+ ++"If it inserted no characters because it caught an exception thrown +while extracting characters from sb and ..." +
+ ++However, we are not extracting from sb, but extracting from the +basic_istream (*this) and inserting into sb. I can't really tell if +"extracting" or "sb" is a typo. +
+ +[ +Sydney: Definitely a real issue. We are, indeed, extracting characters +from an istream and not from sb. The problem was there in the FDIS and +wasn't fixed by issue 64. Probably what was intended was +to have *this instead of sb. We're talking about the exception flag +state of a basic_istream object, and there's only one basic_istream +object in this discussion, so that would be a consistent +interpretation. (But we need to be careful: the exception policy of +this member function must be consistent with that of other +extractors.) PJP will provide wording. +]
+ +Proposed resolution:
+Change the sentence from:
+ ++If it inserted no characters because it caught an exception thrown +while extracting characters from sb and failbit is on in exceptions(), +then the caught exception is rethrown. ++ +to:
+ ++If it inserted no characters because it caught an exception thrown +while extracting characters from *this and failbit is on in exceptions(), +then the caught exception is rethrown. +
414. Which iterators are invalidated by v.erase()?
Section: 23.2.4.3 [lib.vector.modifiers] Status: WP Submitter: Matt Austern Date: 19 Aug 2003
@@ -11975,7 +12236,7 @@ erase". and references in parallel, and it would seem counterintuitive to say that a reference to an erased value remains valid.
-415. behavior of std::ws
Section: 27.6.1.4 [lib.istream.manip] Status: DR Submitter: Martin Sebor Date: 18 Sep 2003
+415. behavior of std::ws
Section: 27.6.1.4 [lib.istream.manip] Status: WP Submitter: Martin Sebor Date: 18 Sep 2003
According to 27.6.1.4, the ws() manipulator is not required to construct the sentry object. The manipulator is also not a member function so the @@ -12023,7 +12284,7 @@ allowed to just declare it without providing a full definition? already says. We don't want to make anything implementation defined, because that imposes new requirements in implementations.
-425. return value of std::get_temporary_buffer
Section: 20.4.3 [lib.temporary.buffer] Status: DR Submitter: Martin Sebor Date: 18 Sep 2003
+425. return value of std::get_temporary_buffer
Section: 20.4.3 [lib.temporary.buffer] Status: WP Submitter: Martin Sebor Date: 18 Sep 2003
The standard is not clear about the requirements on the value returned from a call to get_temporary_buffer(0). In particular, it fails to specify whether @@ -12038,7 +12299,7 @@ values if no storage can be obtained" to "...or a pair of 0 values if no storage can be obtained or if n <= 0."
[Kona: Matt provided wording]
-426. search_n(), fill_n(), and generate_n() with negative n
Section: 25.1.9 [lib.alg.search], 25.2.5 [lib.alg.fill], 25.2.6 [lib.alg.generate] Status: DR Submitter: Martin Sebor Date: 18 Sep 2003
+426. search_n(), fill_n(), and generate_n() with negative n
Section: 25.1.9 [lib.alg.search], 25.2.5 [lib.alg.fill], 25.2.6 [lib.alg.generate] Status: WP Submitter: Martin Sebor Date: 18 Sep 2003
The complexity requirements for these function templates are incorrect (or don't even make sense) for negative n:
@@ -12129,7 +12390,7 @@ which is most likely not the intent. option, on the grounds that duplicating text always risks the possibility that it might be duplicated incorrectly.
-432. stringbuf::overflow() makes only one write position available
Section: 27.7.1.3 [lib.stringbuf.virtuals] Status: DR Submitter: Christian W Brock Date: 24 Sep 2003
+432. stringbuf::overflow() makes only one write position available
Section: 27.7.1.3 [lib.stringbuf.virtuals] Status: WP Submitter: Christian W Brock Date: 24 Sep 2003
27.7.1.3 par 8 says:
Notes: The function can make a write position available only if @@ -12400,7 +12661,47 @@ longer allowable since [pbase(), epptr()) may now contain uninitialized characters. Positioning is only allowable over the initialized range.
-435. bug in DR 25
Section: 21.3.7.9 [lib.string.io] Status: DR Submitter: Martin Sebor Date: 15 Oct 2003
+434. bitset::to_string() hard to use
Section: 23.3.5.2 [lib.bitset.members] Status: DR Submitter: Martin Sebor Date: 15 Oct 2003
++It has been pointed out a number of times that the bitset to_string() member +function template is tedious to use since callers must explicitly specify the +entire template argument list (3 arguments). At least two implementations +provide a number of overloads of this template to make it easier to use. +
+Proposed resolution:
+In order to allow callers to specify no template arguments at all, just the +first one (charT), or the first 2 (charT and traits), in addition to all +three template arguments, add the following three overloads to both the +interface (declarations only) of the class template bitset as well as to +section 23.3.5.2, immediately after p34, the Returns clause of the existing +to_string() member function template:
+ +template <class charT, class traits> + basic_string<charT, traits, allocator<charT> > + to_string () const; + + -34.1- Returns: to_string<charT, traits, allocator<charT> >(). + + template <class charT> + basic_string<charT, char_traits<charT>, allocator<charT> > + to_string () const; + + -34.2- Returns: to_string<charT, char_traits<charT>, allocator<charT> >(). + + basic_string<char, char_traits<char>, allocator<char> > + to_string () const; + + -34.3- Returns: to_string<char, char_traits<char>, allocator<char> >(). ++ +[Kona: the LWG agrees that this is an improvement over the + status quo. Dietmar thought about an alternative using a proxy + object but now believes that the proposed resolution above is the + right choice. +]
+ +
+435. bug in DR 25
Section: 21.3.7.9 [lib.string.io] Status: WP Submitter: Martin Sebor Date: 15 Oct 2003
It has been pointed out that the proposed resolution in DR 25 may not be @@ -12473,7 +12774,330 @@ template parameter.
text.]
-441. Is fpos::state const?
Section: 27.4.3 [lib.fpos] Status: DR Submitter: Vincent Leloup Date: 17 Nov 2003
+438. Ambiguity in the "do the right thing" clause
Section: 23.1.1 [lib.sequence.reqmts] Status: DR Submitter: Howard Hinnant Date: 20 Oct 2003
+ +Section 23.1.1 [lib.sequence.reqmts], paragraphs 9-11, fixed up the problem +noticed with statements like:
+vector<int> v(10, 1); ++ +The intent of the above statement was to construct with:
+vector(size_type, const value_type&); ++ +but early implementations failed to compile as they bound to:
+template <class InputIterator> +vector(InputIterator f, InputIterator l); ++instead.
+ +Paragraphs 9-11 say that if InputIterator is an integral type, then the +member template constructor will have the same effect as:
+vector<static_cast<size_type>(f), static_cast<value_type>(l)); ++(and similarly for the other member template functions of sequences).
+ +There is also a note that describes one implementation technique:
++ One way that sequence implementors can satisfy this requirement is to + specialize the member template for every integral type. ++ +This might look something like:
+++ +template <class T> +struct vector +{ + typedef unsigned size_type; + + explicit vector(size_type) {} + vector(size_type, const T&) {} + + template <class I> + vector(I, I); + + // ... +}; + +template <class T> +template <class I> +vector<T>::vector(I, I) { ... } + +template <> +template <> +vector<int>::vector(int, int) { ... } + +template <> +template <> +vector<int>::vector(unsigned, unsigned) { ... } + +// ... ++Label this solution 'A'.
+ +The standard also says:
++ Less cumbersome implementation techniques also exist. +++A popular technique is to not specialize as above, but instead catch +every call with the member template, detect the type of InputIterator, +and then redirect to the correct logic. Something like: +
+++ +template <class T> +template <class I> +vector<T>::vector(I f, I l) +{ + choose_init(f, l, int2type<is_integral<I>::value>()); +} + +template <class T> +template <class I> +vector<T>::choose_init(I f, I l, int2type<false>) +{ + // construct with iterators +} + +template <class T> +template <class I> +vector<T>::choose_init(I f, I l, int2type<true>) +{ + size_type sz = static_cast<size_type>(f); + value_type v = static_cast<value_type>(l); + // construct with sz,v +} ++Label this solution 'B'.
+ +Both of these solutions solve the case the standard specifically +mentions:
+vector<int> v(10, 1); // ok, vector size 10, initialized to 1 ++ ++However, (and here is the problem), the two solutions have different +behavior in some cases where the value_type of the sequence is not an +integral type. For example consider: +
++pair<char, char> p('a', 'b'); + vector<vector<pair<char, char> > > d('a', 'b'); ++The second line of this snippet is likely an error. Solution A catches +the error and refuses to compile. The reason is that there is no +specialization of the member template constructor that looks like: +
+template <> +template <> +vector<vector<pair<char, char> > >::vector(char, char) { ... } ++ ++So the expression binds to the unspecialized member template +constructor, and then fails (compile time) because char is not an +InputIterator. +
+ ++Solution B compiles the above example though. 'a' is casted to an +unsigned integral type and used to size the outer vector. 'b' is +static casted to the inner vector using it's explicit constructor: +
+ +explicit vector(size_type n); ++ ++and so you end up with a static_cast<size_type>('a') by +static_cast<size_type>('b') matrix. +
+ ++It is certainly possible that this is what the coder intended. But the +explicit qualifier on the inner vector has been thwarted at any rate. +
+ ++The standard is not clear whether the expression: +
+ +vector<vector<pair<char, char> > > d('a', 'b'); ++ ++(and similar expressions) are: +
+ ++
+ +- undefined behavior.
+- illegal and must be rejected.
+- legal and must be accepted.
+My preference is listed in the order presented.
+ +There are still other techniques for implementing the requirements of +paragraphs 9-11, namely the "restricted template technique" (e.g. +enable_if). This technique is the most compact and easy way of coding +the requirements, and has the behavior of #2 (rejects the above +expression). +
+ ++Choosing 1 would allow all implementation techniques I'm aware of. +Choosing 2 would allow only solution 'A' and the enable_if technique. +Choosing 3 would allow only solution 'B'. +
+ ++Possible wording for a future standard if we wanted to actively reject +the expression above would be to change "static_cast" in paragraphs +9-11 to "implicit_cast" where that is defined by: +
+ +++ +template <class T, class U> +inline +T implicit_cast(const U& u) +{ + return u; +} ++Proposed resolution:
+ +Replace 23.1.1 [lib.sequence.reqmts] paragraphs 9 - 11 with: + +For every sequence defined in this clause and in clause lib.strings:
+ ++
+ +- +
+ +If the constructor
+template <class InputIterator> + X(InputIterator f, InputIterator l, + const allocator_type& a = allocator_type()) ++is called with a type InputIterator that does not qualify as + an input iterator, then the constructor will behave as if the + overloaded constructor:
+X(size_type, const value_type& = value_type(), + const allocator_type& = allocator_type()) ++were called instead, with the arguments static_cast<size_type>(f), l and a, respectively.
+- +
+If the member functions of the forms:
+template <class InputIterator> // such as insert() + rt fx1(iterator p, InputIterator f, InputIterator l); + + template <class InputIterator> // such as append(), assign() + rt fx2(InputIterator f, InputIterator l); + + template <class InputIterator> // such as replace() + rt fx3(iterator i1, iterator i2, InputIterator f, InputIterator l); ++are called with a type InputIterator that does not qualify as + an input iterator, then these functions will behave as if the + overloaded member functions:
+rt fx1(iterator, size_type, const value_type&); + + rt fx2(size_type, const value_type&); + + rt fx3(iterator, iterator, size_type, const value_type&); ++were called instead, with the same arguments.
+In the previous paragraph the alternative binding will fail if f +is not implicitly convertible to X::size_type or if l is not implicitly +convertible to X::value_type.
+ ++The extent to which an implementation determines that a type cannot be +an input iterator is unspecified, except that as a minimum integral +types shall not qualify as input iterators. +
+ + + +[ +Kona: agreed that the current standard requires v('a', 'b') +to be accepted, and also agreed that this is surprising behavior. The +LWG considered several options, including something like +implicit_cast, which doesn't appear to be quite what we want. We +considered Howards three options: allow acceptance or rejection, +require rejection as a compile time error, and require acceptance. By +straw poll (1-6-1), we chose to require a compile time error. +Post-Kona: Howard provided wording. +]
+ +[ +Sydney: The LWG agreed with this general direction, but there was some +discomfort with the wording in the original proposed resolution. +Howard submitted new wording, and we will review this again in +Redmond. +]
+ +[Redmond: one very small change in wording: the first argument + is cast to size_t. This fixes the problem of something like + vector<vector<int> >(5, 5), where int is not + implicitly convertible to the value type.]
+ +Rationale:
+The proposed resolution fixes:
+ +vector<int> v(10, 1); ++ ++since as integral types 10 and 1 must be disqualified as input +iterators and therefore the (size,value) constructor is called (as +if).
+ +The proposed resolution breaks:
+ +vector<vector<T> > v(10, 1); ++ ++because the integral type 1 is not *implicitly* convertible to +vector<T>. The wording above requires a diagnostic.
+ ++The proposed resolution leaves the behavior of the following code +unspecified. +
+ +struct A + { + operator int () const {return 10;} + }; + + struct B + { + B(A) {} + }; + + vector<B> v(A(), A()); ++ ++The implementation may or may not detect that A is not an input +iterator and employee the (size,value) constructor. Note though that +in the above example if the B(A) constructor is qualified explicit, +then the implementation must reject the constructor as A is no longer +implicitly convertible to B. +
+
+441. Is fpos::state const?
Section: 27.4.3 [lib.fpos] Status: WP Submitter: Vincent Leloup Date: 17 Nov 2003
In section 27.4.3.1 [lib.fpos.members] fpos<stateT>::state() is declared non const, but in section 27.4.3 [lib.fpos] it is declared const. @@ -12484,7 +13108,7 @@ In section 27.4.3.1
442. sentry::operator bool() inconsistent signature
Section: 27.6.2.3 [lib.ostream::sentry] Status: DR Submitter: Vincent Leloup Date: 18 Nov 2003
+442. sentry::operator bool() inconsistent signature
Section: 27.6.2.3 [lib.ostream::sentry] Status: WP Submitter: Vincent Leloup Date: 18 Nov 2003
In section 27.6.2.3 [lib.ostream::sentry] paragraph 4, in description part basic_ostream<charT, traits>::sentry::operator bool() is declared @@ -12497,7 +13121,7 @@ In section 27.6.2.3
443. filebuf::close() inconsistent use of EOF
Section: 27.8.1.3 [lib.filebuf.members] Status: DR Submitter: Vincent Leloup Date: 20 Nov 2003
+443. filebuf::close() inconsistent use of EOF
Section: 27.8.1.3 [lib.filebuf.members] Status: WP Submitter: Vincent Leloup Date: 20 Nov 2003
In section 27.8.1.3 [lib.filebuf.members] par6, in effects description of basic_filebuf<charT, traits>::close(), overflow(EOF) is used twice; @@ -12508,7 +13132,204 @@ should be overflow(traits::eof()). Change overflow(EOF) to overflow(traits::eof()).
-448. Random Access Iterators over abstract classes
Section: 24.1.5 [lib.random.access.iterators] Status: DR Submitter: Dave Abrahams Date: 7 Jan 2004
+444. Bad use of casts in fstream
Section: 27.8.1 [lib.fstreams] Status: DR Submitter: Vincent Leloup Date: 20 Nov 2003
++27.8.1.7 [lib.ifstream.members] p1, 27.8.1.10 [lib.ofstream.members] p1, 27.8.1.13 [lib.fstream.members] p1 seems have same problem as exposed in LWG issue +252. +
+Proposed resolution:
+ +[Sydney: Genuine defect. 27.8.1.13 needs a cast to cast away + constness. The other two places are stylistic: we could change the + C-style casts to const_cast. Post-Sydney: Howard provided wording. +]
+ +Change 27.8.1.7/1 from:
++ Returns: (basic_filebuf<charT,traits>*)&sb. ++ +to:
++ Returns: const_cast<basic_filebuf<charT,traits>*>(&sb). ++ +Change 27.8.1.10/1 from:
++ Returns: (basic_filebuf<charT,traits>*)&sb. ++ +to:
++ Returns: const_cast<basic_filebuf<charT,traits>*>(&sb). ++ +Change 27.8.1.13/1 from:
++ Returns: &sb. ++ +to:
++ Returns: const_cast<basic_filebuf<charT,traits>*>(&sb). ++ + + +
+445. iterator_traits::reference unspecified for some iterator categories
Section: 24.3.1 [lib.iterator.traits] Status: DR Submitter: Dave Abrahams Date: 9 Dec 2003
++The standard places no restrictions at all on the reference type +of input, output, or forward iterators (for forward iterators it +only specifies that *x must be value_type& and doesn't mention +the reference type). Bidirectional iterators' reference type is +restricted only by implication, since the base iterator's +reference type is used as the return type of reverse_iterator's +operator*, which must be T& in order to be a conforming forward +iterator. +
+ ++Here's what I think we ought to be able to expect from an input +or forward iterator's reference type R, where a is an iterator +and V is its value_type +
+ ++
+ +- + *a is convertible to R +
+ +- + R is convertible to V +
+ +- + static_cast<V>(static_cast<R>(*a)) is equivalent to + static_cast<V>(*a) +
+A mutable forward iterator ought to satisfy, for x of type V:
+- + { R r = *a; r = x; } is equivalent to *a = x; +
+ ++I think these requirements capture existing container iterators +(including vector<bool>'s), but render istream_iterator invalid; +its reference type would have to be changed to a constant +reference. +
+ + ++(Jeremy Siek) During the discussion in Sydney, it was felt that a +simpler long term solution for this was needed. The solution proposed +was to require reference to be the same type as *a +and pointer to be the same type as a->. Most +iterators in the Standard Library already meet this requirement. Some +iterators are output iterators, and do not need to meet the +requirement, and others are only specified through the general +iterator requirements (which will change with this resolution). The +sole case where there is an explicit definition of the reference type +that will need to change is istreambuf_iterator which returns +charT from operator* but has a reference type of +charT&. We propose changing the reference type of +istreambuf_iterator to charT. +
+ +The other option for resolving the issue with pointer, + mentioned in the note below, is to remove pointer + altogether. I prefer placing requirements on pointer to + removing it for two reasons. First, pointer will become + useful for implementing iterator adaptors and in particular, + reverse_iterator will become more well defined. Second, + removing pointer is a rather drastic and publicly-visible + action to take.
+ +The proposed resolution technically enlarges the requirements for +iterators, which means there are existing iterators (such as +istreambuf_iterator, and potentially some programmer-defined +iterators) that will no longer meet the requirements. Will this break +existing code? The scenario in which it would is if an algorithm +implementation (say in the Standard Library) is changed to rely on +iterator_traits::reference, and then is used with one of the +iterators that do not have an appropriately defined +iterator_traits::reference. +
+ + +The proposed resolution makes one other subtle change. Previously, +it was required that output iterators have a difference_type +and value_type of void, which means that a forward +iterator could not be an output iterator. This is clearly a mistake, +so I've changed the wording to say that those types may be +void. +
+ +Proposed resolution:
+ +In 24.3.1 [lib.iterator.traits], after:
+ ++be defined as the iterator's difference type, value type and iterator +category, respectively. ++ +add
+ ++In addition, the types ++ +iterator_traits<Iterator>::reference +iterator_traits<Iterator>::pointer ++must be defined as the iterator's reference and pointer types, that +is, the same type as the type of *a and a->, +respectively. +In 24.3.1 [lib.iterator.traits], change:
+ ++In the case of an output iterator, the types ++ +iterator_traits<Iterator>::difference_type +iterator_traits<Iterator>::value_type ++are both defined as void. +to:
++In the case of an output iterator, the types ++ +iterator_traits<Iterator>::difference_type +iterator_traits<Iterator>::value_type +iterator_traits<Iterator>::reference +iterator_traits<Iterator>::pointer ++may be defined as void. +In 24.5.3 [lib.istreambuf.iterator], change:
+++typename traits::off_type, charT*, charT&> ++to:
+++ +typename traits::off_type, charT*, charT> ++[ +Redmond: there was concern in Sydney that this might not be the only place +where things were underspecified and needed to be changed. Jeremy +reviewed iterators in the standard and confirmed that nothing else +needed to be changed. +]
+ +
+448. Random Access Iterators over abstract classes
Section: 24.1.5 [lib.random.access.iterators] Status: WP Submitter: Dave Abrahams Date: 7 Jan 2004
Table 76, the random access iterator requirement table, says that the return type of a[n] must be "convertible to T". When an iterator's @@ -12520,7 +13341,7 @@ Surely this isn't an intended restriction? Change the return type to "convertible to T const&".
-449. Library Issue 306 Goes Too Far
Section: 18.1 [lib.support.types] Status: DR Submitter: Pete Becker Date: 15 Jan 2004
+449. Library Issue 306 Goes Too Far
Section: 18.1 [lib.support.types] Status: WP Submitter: Pete Becker Date: 15 Jan 2004
Original text:
The macro offsetof accepts a restricted set of type arguments in this @@ -12549,5 +13370,126 @@ the results are undefined. The result of applying the offsetof macro to a field that is a static data member or a function member is undefined."+
+453. basic_stringbuf::seekoff need not always fail for an empty stream
Section: 27.7.1.3 [lib.stringbuf.virtuals] Status: DR Submitter: Bill Plauger Date: 30 Jan 2004
+pos_type basic_stringbuf::seekoff(off_type, ios_base::seekdir, + ios_base::openmode); +++is obliged to fail if nothing has been inserted into the stream. This +is unnecessary and undesirable. It should be permissible to seek to +an effective offset of zero.
+ +[ + Sydney: Agreed that this is an annoying problem: seeking to zero should be + legal. Bill will provide wording. +]
+ +Proposed resolution:
+Change the sentence from:
++For a sequence to be positioned, if its next pointer (either +gptr() or pptr()) is a null pointer, the positioning operation +fails. ++ +to:
+ ++For a sequence to be positioned, if its next pointer (either +gptr() or pptr()) is a null pointer and the new offset newoff +is nonzero, the positioning operation fails. ++
+455. cerr::tie() and wcerr::tie() are overspecified
Section: 27.3 [lib.iostream.objects] Status: DR Submitter: Bill Plauger Date: 30 Jan 2004
++Both cerr::tie() and wcerr::tie() are obliged to be null at program +startup. This is overspecification and overkill. It is both traditional +and useful to tie cerr to cout, to ensure that standard output is drained +whenever an error message is written. This behavior should at least be +permitted if not required. Same for wcerr::tie(). +
+Proposed resolution:
+ +Add to the description of cerr:
++After the object cerr is initialized, cerr.tie() returns &cout. +Its state is otherwise the same as required for basic_ios<char>::init +(lib.basic.ios.cons). ++ +Add to the description of wcerr:
+ ++After the object wcerr is initialized, wcerr.tie() returns &wcout. +Its state is otherwise the same as required for basic_ios<wchar_t>::init +(lib.basic.ios.cons). ++ +[Sydney: straw poll (3-1): we should require, not just + permit, cout and cerr to be tied on startup. Pre-Redmond: Bill will + provide wording.]
+
+457. bitset constructor: incorrect number of initialized bits
Section: 23.3.5.1 [lib.bitset.cons] Status: DR Submitter: Dag Henriksson Date: 30 Jan 2004
++The constructor from unsigned long says it initializes "the first M +bit positions to the corresponding bit values in val. M is the smaller +of N and the value CHAR_BIT * sizeof(unsigned long)." +
+ ++Object-representation vs. value-representation strikes again. CHAR_BIT * +sizeof (unsigned long) does not give us the number of bits an unsigned long +uses to hold the value. Thus, the first M bit position above is not +guaranteed to have any corresponding bit values in val. +
+Proposed resolution:
+In 23.3.5.1 [lib.bitset.cons] paragraph 2, change "M is the smaller of + N and the value CHAR_BIT * sizeof (unsigned long). (249)" to + "M is the smaller of N and the number of bits in + the value representation (section 3.9 [basic.types]) of unsigned + long." +
+
+460. Default modes missing from basic_fstream member specifications
Section: 27.8.1 [lib.fstreams] Status: DR Submitter: Ben Hutchings Date: 1 Apr 2004
++The second parameters of the non-default constructor and of the open +member function for basic_fstream, named "mode", are optional +according to the class declaration in 27.8.1.11 [lib.fstream]. The +specifications of these members in 27.8.1.12 [lib.fstream.cons] and +27.8.1.13 lib.fstream.members] disagree with this, though the +constructor declaration has the "explicit" function-specifier implying +that it is intended to be callable with one argument. +
+Proposed resolution:
+In 27.8.1.12 [lib.fstream.cons], change
+explicit basic_fstream(const char* s, ios_base::openmode mode); ++to
+explicit basic_fstream(const char* s, + ios_base::openmode mode = ios_base::in|ios_base::out); ++In 27.8.1.13 [lib.fstream.members], change
+void open(const char*s, ios_base::openmode mode); ++to
+ void open(const char*s, + ios_base::openmode mode = ios_base::in|ios_base::out); +
+469. vector<bool> ill-formed relational operators
Section: 23.2.5 [lib.vector.bool] Status: DR Submitter: Martin Sebor Date: 28 Jun 2004
+ ++The overloads of relational operators for vector<bool> specified +in [lib.vector.bool] are redundant (they are semantically identical +to those provided for the vector primary template) and may even be +diagnosed as ill-formed (refer to Daveed Vandevoorde's explanation +in c++std-lib-13647). +
+ +Proposed resolution:
++Remove all overloads of overloads of relational operators for +vector<bool> from [lib.vector.bool]. +
----- End of document -----