X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Fdoc%2Fhtml%2Fext%2Flwg-defects.html;fp=libstdc%2B%2B-v3%2Fdoc%2Fhtml%2Fext%2Flwg-defects.html;h=5951a9821e2e6bbab7244950efc8367dd7c386a8;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=0000000000000000000000000000000000000000;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/libstdc++-v3/doc/html/ext/lwg-defects.html b/libstdc++-v3/doc/html/ext/lwg-defects.html new file mode 100644 index 00000000..5951a982 --- /dev/null +++ b/libstdc++-v3/doc/html/ext/lwg-defects.html @@ -0,0 +1,29778 @@ + +
+ + + +Doc. no. | +N2728=08-0238 | +
Date: | +2008-08-24 | +
Project: | +Programming Language C++ | +
Reply to: | +Howard Hinnant <howard.hinnant@gmail.com> | +
Reference ISO/IEC IS 14882:1998(E)
+Also see:
+This document contains only library issues which have been closed + by the Library Working Group (LWG) after being found to be defects + in the standard. That is, issues which have a status of DR, + TC, or RR. See the + Library Closed Issues List for issues closed as non-defects. See the + Library Active Issues List for active issues and more information. The + introductory material in that document also applies to this + document.
+ +Section: 17.4.2.2 [using.linkage] Status: TC + Submitter: Beman Dawes Date: 1997-11-16
+View all issues with TC status.
+Discussion:
+The change specified in the proposed resolution below did not make +it into the Standard. This change was accepted in principle at the +London meeting, and the exact wording below was accepted at the +Morristown meeting.
+ + +Proposed resolution:
+Change 17.4.2.2 [using.linkage] paragraph 2 +from:
+ +++ +It is unspecified whether a name from the Standard C library + declared with external linkage has either extern "C" or + extern "C++" linkage.
+
to:
+ +++ + + + + +Whether a name from the Standard C library declared with external + linkage has extern "C" or extern "C++" linkage + is implementation defined. It is recommended that an implementation + use extern "C++" linkage for this purpose.
+
Section: 18.4 [support.start.term] Status: TC + Submitter: Steve Clamage Date: 1997-12-12
+View all issues with TC status.
+Discussion:
+We appear not to have covered all the possibilities of
+ exit processing with respect to
+atexit registration.
+
+Example 1: (C and C++)
#include <stdlib.h> + void f1() { } + void f2() { atexit(f1); } + + int main() + { + atexit(f2); // the only use of f2 + return 0; // for C compatibility + }+ +
At program exit, f2 gets called due to its registration in +main. Running f2 causes f1 to be newly registered during the exit +processing. Is this a valid program? If so, what are its +semantics?
+ ++Interestingly, neither the C standard, nor the C++ draft standard nor +the forthcoming C9X Committee Draft says directly whether you can +register a function with atexit during exit processing.
+ ++All 3 standards say that functions are run in reverse order of their +registration. Since f1 is registered last, it ought to be run first, +but by the time it is registered, it is too late to be first.
+ +If the program is valid, the standards are self-contradictory about +its semantics.
+ +Example 2: (C++ only)
+ ++ void F() { static T t; } // type T has a destructor + + int main() + { + atexit(F); // the only use of F + } ++ +
Function F registered with atexit has a local static variable t, +and F is called for the first time during exit processing. A local +static object is initialized the first time control flow passes +through its definition, and all static objects are destroyed during +exit processing. Is the code valid? If so, what are its semantics?
+ ++Section 18.3 "Start and termination" says that if a function +F is registered with atexit before a static object t is initialized, F +will not be called until after t's destructor completes.
+ ++In example 2, function F is registered with atexit before its local +static object O could possibly be initialized. On that basis, it must +not be called by exit processing until after O's destructor +completes. But the destructor cannot be run until after F is called, +since otherwise the object could not be constructed in the first +place.
+ +If the program is valid, the standard is self-contradictory about +its semantics.
+ +I plan to submit Example 1 as a public comment on the C9X CD, with +a recommendation that the results be undefined. (Alternative: make it +unspecified. I don't think it is worthwhile to specify the case where +f1 itself registers additional functions, each of which registers +still more functions.)
+ +I think we should resolve the situation in the whatever way the C +committee decides.
+ +For Example 2, I recommend we declare the results undefined.
+ +[See reflector message lib-6500 for further discussion.]
+ + + + +Proposed resolution:
+Change section 18.3/8 from:
+++ First, objects with static storage duration are destroyed and + functions registered by calling atexit are called. Objects with + static storage duration are destroyed in the reverse order of the + completion of their constructor. (Automatic objects are not + destroyed as a result of calling exit().) Functions registered with + atexit are called in the reverse order of their registration. A + function registered with atexit before an object obj1 of static + storage duration is initialized will not be called until obj1's + destruction has completed. A function registered with atexit after + an object obj2 of static storage duration is initialized will be + called before obj2's destruction starts. +
to:
++ + ++ First, objects with static storage duration are destroyed and + functions registered by calling atexit are called. Non-local objects + with static storage duration are destroyed in the reverse order of + the completion of their constructor. (Automatic objects are not + destroyed as a result of calling exit().) Functions registered with + atexit are called in the reverse order of their registration, except + that a function is called after any previously registered functions + that had already been called at the time it was registered. A + function registered with atexit before a non-local object obj1 of + static storage duration is initialized will not be called until + obj1's destruction has completed. A function registered with atexit + after a non-local object obj2 of static storage duration is + initialized will be called before obj2's destruction starts. A local + static object obj3 is destroyed at the same time it would be if a + function calling the obj3 destructor were registered with atexit at + the completion of the obj3 constructor. +
Rationale:
+See 99-0039/N1215, October 22, 1999, by Stephen D. Clamage for the analysis +supporting to the proposed resolution.
+ + + + + +Section: 21.3.6.8 [string::swap] Status: TC + Submitter: Jack Reeves Date: 1997-12-11
+View all other issues in [string::swap].
+View all issues with TC status.
+Duplicate of: 87
+Discussion:
+At the very end of the basic_string class definition is the signature: int +compare(size_type pos1, size_type n1, const charT* s, size_type n2 = npos) const; In the +following text this is defined as: returns +basic_string<charT,traits,Allocator>(*this,pos1,n1).compare( +basic_string<charT,traits,Allocator>(s,n2);
+ +Since the constructor basic_string(const charT* s, size_type n, const Allocator& a += Allocator()) clearly requires that s != NULL and n < npos and further states that it +throws length_error if n == npos, it appears the compare() signature above should always +throw length error if invoked like so: str.compare(1, str.size()-1, s); where 's' is some +null terminated character array.
+ +This appears to be a typo since the obvious intent is to allow either the call above or +something like: str.compare(1, str.size()-1, s, strlen(s)-1);
+ +This would imply that what was really intended was two signatures int compare(size_type +pos1, size_type n1, const charT* s) const int compare(size_type pos1, size_type n1, const +charT* s, size_type n2) const; each defined in terms of the corresponding constructor.
+ + +Proposed resolution:
+Replace the compare signature in 21.3 [basic.string] +(at the very end of the basic_string synopsis) which reads:
+ +++ +int compare(size_type pos1, size_type n1,
+
+ const charT* s, + size_type n2 = npos) const;
with:
+ +++ +int compare(size_type pos1, size_type n1,
+
+ const charT* s) const;
+ int compare(size_type pos1, size_type n1,
+ const charT* s, + size_type n2) const;
Replace the portion of 21.3.6.8 [string::swap] +paragraphs 5 and 6 which read:
+ +++ +int compare(size_type pos, size_type n1,
+
+ charT * s, size_type n2 + = npos) const;
+ Returns:
+ basic_string<charT,traits,Allocator>(*this, pos, n1).compare(
+ + basic_string<charT,traits,Allocator>( s, n2))
with:
+ +++ +int compare(size_type pos, size_type n1,
+
+ const charT * s) const;
+ Returns:
+ basic_string<charT,traits,Allocator>(*this, pos, n1).compare(
+ + basic_string<charT,traits,Allocator>( s ))
+
+ int compare(size_type pos, size_type n1,
+ const charT * s, + size_type n2) const;
+ Returns:
+ basic_string<charT,traits,Allocator>(*this, pos, n1).compare(
+ + basic_string<charT,traits,Allocator>( s, n2))
Editors please note that in addition to splitting the signature, the third argument +becomes const, matching the existing synopsis.
+ + +Rationale:
+While the LWG dislikes adding signatures, this is a clear defect in +the Standard which must be fixed. The same problem was also +identified in issues 7 (item 5) and 87.
+ + + + + +Section: 21 [strings] Status: TC + Submitter: Matt Austern Date: 1997-12-15
+View all other issues in [strings].
+View all issues with TC status.
+Discussion:
+(1) In 21.3.6.4 [string::insert], the description of template +<class InputIterator> insert(iterator, InputIterator, +InputIterator) makes no sense. It refers to a member function that +doesn't exist. It also talks about the return value of a void +function.
+ +(2) Several versions of basic_string::replace don't appear in the +class synopsis.
+ +(3) basic_string::push_back appears in the synopsis, but is never +described elsewhere. In the synopsis its argument is const charT, +which doesn't makes much sense; it should probably be charT, or +possible const charT&.
+ +(4) basic_string::pop_back is missing.
+ +(5) int compare(size_type pos, size_type n1, charT* s, size_type n2 += npos) make no sense. First, it's const charT* in the synopsis and +charT* in the description. Second, given what it says in RETURNS, +leaving out the final argument will always result in an exception +getting thrown. This is paragraphs 5 and 6 of +21.3.6.8 [string::swap]
+ +(6) In table 37, in section 21.1.1 [char.traits.require], +there's a note for X::move(s, p, n). It says "Copies correctly +even where p is in [s, s+n)". This is correct as far as it goes, +but it doesn't go far enough; it should also guarantee that the copy +is correct even where s in in [p, p+n). These are two orthogonal +guarantees, and neither one follows from the other. Both guarantees +are necessary if X::move is supposed to have the same sort of +semantics as memmove (which was clearly the intent), and both +guarantees are necessary if X::move is actually supposed to be +useful.
+ + +Proposed resolution:
+ITEM 1: In 21.3.5.4 [lib.string::insert], change paragraph 16 to
+
+ EFFECTS: Equivalent to insert(p - begin(), basic_string(first, last)).
+
+ITEM 2: Not a defect; the Standard is clear.. There are ten versions of replace() in
+the synopsis, and ten versions in 21.3.5.6 [lib.string::replace].
+
+ITEM 3: Change the declaration of push_back in the string synopsis (21.3,
+[lib.basic.string]) from:
void push_back(const charT)
+
+to
+
+ void push_back(charT)
+
+Add the following text immediately after 21.3.5.2 [lib.string::append], paragraph 10.
+
+ void basic_string::push_back(charT c);
+ EFFECTS: Equivalent to append(static_cast<size_type>(1), c);
+
+ITEM 4: Not a defect. The omission appears to have been deliberate.
+
+ITEM 5: Duplicate; see issue 5 (and 87).
+
+ITEM 6: In table 37, Replace:
+
+ "Copies correctly even where p is in [s, s+n)."
+
+with:
+
+ "Copies correctly even where the ranges [p, p+n) and [s,
+s+n) overlap."
Section: 22.1.1.5 [locale.statics] Status: TC + Submitter: Matt Austern Date: 1997-12-24
+View all issues with TC status.
+Discussion:
+It appears there's an important guarantee missing from clause +22. We're told that invoking locale::global(L) sets the C locale if L +has a name. However, we're not told whether or not invoking +setlocale(s) sets the global C++ locale.
+ +The intent, I think, is that it should not, but I can't find any +such words anywhere.
+ + +Proposed resolution:
+Add a sentence at the end of 22.1.1.5 [locale.statics], +paragraph 2:
+ +++ + + + + +No library function other than locale::global() shall affect + the value returned by locale().
+ +
Section: 18.5.1 [new.delete] Status: TC + Submitter: Steve Clamage Date: 1998-01-04
+View all issues with TC status.
+Discussion:
+Scott Meyers, in a comp.std.c++ posting: I just noticed that +section 3.7.3.1 of CD2 seems to allow for the possibility that all +calls to operator new(0) yield the same pointer, an implementation +technique specifically prohibited by ARM 5.3.3.Was this prohibition +really lifted? Does the FDIS agree with CD2 in the regard? [Issues +list maintainer's note: the IS is the same.]
+ + +Proposed resolution:
+Change the last paragraph of 3.7.3 from:
+++Any allocation and/or deallocation functions defined in a C++ program shall + conform to the semantics specified in 3.7.3.1 and 3.7.3.2.
+
to:
+++Any allocation and/or deallocation functions defined in a C++ program, + including the default versions in the library, shall conform to the semantics + specified in 3.7.3.1 and 3.7.3.2.
+
Change 3.7.3.1/2, next-to-last sentence, from :
+++If the size of the space requested is zero, the value returned shall not be + a null pointer value (4.10).
+
to:
+++Even if the size of the space requested is zero, the request can fail. If + the request succeeds, the value returned shall be a non-null pointer value + (4.10) p0 different from any previously returned value p1, unless that value + p1 was since passed to an operator delete.
+
5.3.4/7 currently reads:
+++When the value of the expression in a direct-new-declarator is zero, the + allocation function is called to allocate an array with no elements. The + pointer returned by the new-expression is non-null. [Note: If the library + allocation function is called, the pointer returned is distinct from the + pointer to any other object.]
+
Retain the first sentence, and delete the remainder.
+18.5.1 currently has no text. Add the following:
+++Except where otherwise specified, the provisions of 3.7.3 apply to the + library versions of operator new and operator delete.
+
To 18.5.1.3, add the following text:
+++ + +The provisions of 3.7.3 do not apply to these reserved placement forms of + operator new and operator delete.
+
Rationale:
+See 99-0040/N1216, October 22, 1999, by Stephen D. Clamage for the analysis +supporting to the proposed resolution.
+ + + + + +Section: 23.3.5 [template.bitset] Status: TC + Submitter: Matt Austern Date: 1998-01-22
+View all other issues in [template.bitset].
+View all issues with TC status.
+Discussion:
+(1) bitset<>::operator[] is mentioned in the class synopsis (23.3.5), but it is +not documented in 23.3.5.2.
+ +(2) The class synopsis only gives a single signature for bitset<>::operator[], +reference operator[](size_t pos). This doesn't make much sense. It ought to be overloaded +on const. reference operator[](size_t pos); bool operator[](size_t pos) const.
+ +(3) Bitset's stream input function (23.3.5.3) ought to skip all whitespace before +trying to extract 0s and 1s. The standard doesn't explicitly say that, though. This should +go in the Effects clause.
+ + +Proposed resolution:
+ITEMS 1 AND 2:
+
+In the bitset synopsis (23.3.5 [template.bitset]),
+replace the member function
+
+ reference operator[](size_t pos);
+
+with the two member functions
+
+ bool operator[](size_t pos) const;
+ reference operator[](size_t pos);
+
+Add the following text at the end of 23.3.5.2 [bitset.members],
+immediately after paragraph 45:
++ + +bool operator[](size_t pos) const;
+
+ Requires: pos is valid
+ Throws: nothing
+ Returns: test(pos)
+
+ bitset<N>::reference operator[](size_t pos);
+ Requires: pos is valid
+ Throws: nothing
+ Returns: An object of type bitset<N>::reference such that (*this)[pos] + == this->test(pos), and such that (*this)[pos] = val is equivalent to this->set(pos, + val);
Rationale:
+The LWG believes Item 3 is not a defect. "Formatted +input" implies the desired semantics. See 27.6.1.2 [istream.formatted]. +
+ + + + + +Section: 27.6.1.2.3 [istream::extractors] Status: TC + Submitter: William M. Miller Date: 1998-03-03
+View all other issues in [istream::extractors].
+View all issues with TC status.
+Discussion:
+In 27.6.1.2.3, there is a reference to "eos", which is +the only one in the whole draft (at least using Acrobat search), so +it's undefined.
+ + +Proposed resolution:
+In 27.6.1.2.3 [istream::extractors], replace "eos" with +"charT()"
+ + + + + +Section: 22.1.1.3 [locale.members] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale.members].
+View all issues with TC status.
+Discussion:
+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 +paragraph 6: "An instance of a locale is immutable."
+ +History: this member function originally was a constructor. it happened that the +interface it specified had no corresponding language syntax, so it was changed to a member +function. As constructors are never const, there was no "const" in the interface +which was transformed into member "combine". It should have been added at that +time, but the omission was not noticed.
+ + +Proposed resolution:
+In 22.1.1 [locale] and also in 22.1.1.3 [locale.members], add +"const" to the declaration of member combine:
+++ + + + + +template <class Facet> locale combine(const locale& other) const;+
Section: 22.1.1.3 [locale.members] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale.members].
+View all issues with TC status.
+Discussion:
+locale::name() is described as returning a string that can be passed to a locale +constructor, but there is no matching constructor.
+ + +Proposed resolution:
+In 22.1.1.3 [locale.members], paragraph 5, replace +"locale(name())" with +"locale(name().c_str())". +
+ + + + + +Section: 22.2.1.4 [locale.codecvt] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale.codecvt].
+View all issues with TC status.
+Discussion:
+The new virtual members ctype_byname<char>::do_widen and do_narrow did not get +edited in properly. Instead, the member do_widen appears four times, with wrong argument +lists.
+ + +Proposed resolution:
+The correct declarations for the overloaded members +do_narrow and do_widen should be copied +from 22.2.1.3 [facet.ctype.special].
+ + + + + +Section: 22.2.2.1.2 [facet.num.get.virtuals] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View other active issues in [facet.num.get.virtuals].
+View all other issues in [facet.num.get.virtuals].
+View all issues with TC status.
+Discussion:
+This section describes the process of parsing a text boolean value from the input
+stream. It does not say it recognizes either of the sequences "true" or
+"false" and returns the corresponding bool value; instead, it says it recognizes
+only one of those sequences, and chooses which according to the received value of a
+reference argument intended for returning the result, and reports an error if the other
+sequence is found. (!) Furthermore, it claims to get the names from the ctype<>
+facet rather than the numpunct<> facet, and it examines the "boolalpha"
+flag wrongly; it doesn't define the value "loc"; and finally, it computes
+wrongly whether to use numeric or "alpha" parsing.
+
+I believe the correct algorithm is "as if":
// in, err, val, and str are arguments. + err = 0; + const numpunct<charT>& np = use_facet<numpunct<charT> >(str.getloc()); + const string_type t = np.truename(), f = np.falsename(); + bool tm = true, fm = true; + size_t pos = 0; + while (tm && pos < t.size() || fm && pos < f.size()) { + if (in == end) { err = str.eofbit; } + bool matched = false; + if (tm && pos < t.size()) { + if (!err && t[pos] == *in) matched = true; + else tm = false; + } + if (fm && pos < f.size()) { + if (!err && f[pos] == *in) matched = true; + else fm = false; + } + if (matched) { ++in; ++pos; } + if (pos > t.size()) tm = false; + if (pos > f.size()) fm = false; + } + if (tm == fm || pos == 0) { err |= str.failbit; } + else { val = tm; } + return in;+ +
Notice this works reasonably when the candidate strings are both empty, or equal, or +when one is a substring of the other. The proposed text below captures the logic of the +code above.
+ + +Proposed resolution:
+In 22.2.2.1.2 [facet.num.get.virtuals], in the first line of paragraph 14, +change "&&" to "&".
+ +Then, replace paragraphs 15 and 16 as follows:
+ ++ ++ +Otherwise target sequences are determined "as if" by + calling the members falsename() and + truename() of the facet obtained by + use_facet<numpunct<charT> >(str.getloc()). + Successive characters in the range [in,end) (see + [lib.sequence.reqmts]) are obtained and matched against + corresponding positions in the target sequences only as necessary to + identify a unique match. The input iterator in is + compared to end only when necessary to obtain a + character. If and only if a target sequence is uniquely matched, + val is set to the corresponding value.
+ +
++ + + + + +The in iterator is always left pointing one position beyond the last character + successfully matched. If val is set, then err is set to str.goodbit; or to + str.eofbit if, when seeking another character to match, it is found that + (in==end). If val is not set, then err is set to str.failbit; or to + (str.failbit|str.eofbit)if + the reason for the failure was that (in==end). [Example: for targets + true:"a" and false:"abb", the input sequence "a" yields + val==true and err==str.eofbit; the input sequence "abc" yields + err=str.failbit, with in ending at the 'c' element. For targets + true:"1" + and false:"0", the input sequence "1" yields val==true + and err=str.goodbit. For empty targets (""), any input sequence yields + err==str.failbit. --end example]
+
Section: 22.2.2.1.1 [facet.num.get.members] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [facet.num.get.members].
+View all issues with TC status.
+Discussion:
+In the list of num_get<> non-virtual members on page 22-23, the member +that parses bool values was omitted from the list of definitions of non-virtual +members, though it is listed in the class definition and the corresponding +virtual is listed everywhere appropriate.
+ + +Proposed resolution:
+Add at the beginning of 22.2.2.1.1 [facet.num.get.members] +another get member for bool&, copied from the entry in +22.2.2.1 [locale.num.get].
+ + + + + +Section: 22.2.1.4 [locale.codecvt] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale.codecvt].
+View all issues with TC status.
+Duplicate of: 10
+Discussion:
++In the definitions of codecvt<>::do_out and do_in, they are +specified to return noconv if "no conversion is +needed". This definition is too vague, and does not say +normatively what is done with the buffers. +
+ + +Proposed resolution:
++Change the entry for noconv in the table under paragraph 4 in section +22.2.1.4.2 [locale.codecvt.virtuals] to read: +
+++noconv: internT and externT are the same type, + and input sequence is identical to converted sequence.
+
Change the Note in paragraph 2 to normative text as follows:
+++ + + + + +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).
+
Section: 22.2.3.1.2 [facet.numpunct.virtuals] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all issues with TC status.
+Discussion:
+The synopsis for numpunct<>::do_thousands_sep, and the +definition of numpunct<>::thousands_sep which calls it, specify +that it returns a value of type char_type. Here it is erroneously +described as returning a "string_type".
+ + +Proposed resolution:
+In 22.2.3.1.2 [facet.numpunct.virtuals], above paragraph 2, change +"string_type" to "char_type".
+ + + + + +Section: 22.1.1.1.1 [locale.category] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale.category].
+View all issues with TC status.
+Discussion:
+In the second table in the section, captioned "Required +instantiations", the instantiations for codecvt_byname<> +have been omitted. These are necessary to allow users to construct a +locale by name from facets.
+ + +Proposed resolution:
+Add in 22.1.1.1.1 [locale.category] to the table captioned +"Required instantiations", in the category "ctype" +the lines
+ +++ + + + + +codecvt_byname<char,char,mbstate_t>, +codecvt_byname<wchar_t,char,mbstate_t>+
Section: 27.8.1.9 [ifstream.members] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [ifstream.members].
+View all issues with TC status.
+Discussion:
+The description of basic_istream<>::open leaves unanswered questions about how it +responds to or changes flags in the error status for the stream. A strict reading +indicates that it ignores the bits and does not change them, which confuses users who do +not expect eofbit and failbit to remain set after a successful open. There are three +reasonable resolutions: 1) status quo 2) fail if fail(), ignore eofbit 3) clear failbit +and eofbit on call to open().
+ + +Proposed resolution:
+In 27.8.1.9 [ifstream.members] paragraph 3, and in 27.8.1.13 [ofstream.members] paragraph 3, under open() effects, add a footnote: +
+ +++ + +A successful open does not change the error state.
+
Rationale:
+This may seem surprising to some users, but it's just an instance +of a general rule: error flags are never cleared by the +implementation. The only way error flags are are ever cleared is if +the user explicitly clears them by hand.
+ +The LWG believed that preserving this general rule was +important enough so that an exception shouldn't be made just for this +one case. The resolution of this issue clarifies what the LWG +believes to have been the original intent.
+ + + + + + +Section: 22.2.1.4 [locale.codecvt] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale.codecvt].
+View all issues with TC status.
+Duplicate of: 72
+Discussion:
+The description of codecvt<>::do_out and do_in mentions a +symbol "do_convert" which is not defined in the +standard. This is a leftover from an edit, and should be "do_in +and do_out".
+ + +Proposed resolution:
+In 22.2.1.4 [locale.codecvt], paragraph 3, change +"do_convert" to "do_in or do_out". Also, in 22.2.1.4.2 [locale.codecvt.virtuals], change "do_convert()" to "do_in +or do_out".
+ + + + + +Section: 21.3.8.9 [string.io] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [string.io].
+View all issues with TC status.
+Duplicate of: 67
+Discussion:
+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.
+ + +Proposed resolution:
+Change 21.3.8.9 [string.io] paragraph 4 from:
+
+ "... where n is the smaller of os.width() and str.size();
+..."
+
+to:
+
+ "... where n is the larger of os.width() and str.size();
+..."
Section: 27.6.1.1.3 [istream::sentry] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [istream::sentry].
+View all issues with TC status.
+Discussion:
+In paragraph 6, the code in the example:
+ +template <class charT, class traits = char_traits<charT> > + basic_istream<charT,traits>::sentry( + basic_istream<charT,traits>& is, bool noskipws = false) { + ... + int_type c; + typedef ctype<charT> ctype_type; + const ctype_type& ctype = use_facet<ctype_type>(is.getloc()); + while ((c = is.rdbuf()->snextc()) != traits::eof()) { + if (ctype.is(ctype.space,c)==0) { + is.rdbuf()->sputbackc (c); + break; + } + } + ... + }+ +
fails to demonstrate correct use of the facilities described. In +particular, it fails to use traits operators, and specifies incorrect +semantics. (E.g. it specifies skipping over the first character in the +sequence without examining it.)
+ + +Proposed resolution:
+Remove the example above from 27.6.1.1.3 [istream::sentry] +paragraph 6.
+ + +Rationale:
+The originally proposed replacement code for the example was not +correct. The LWG tried in Kona and again in Tokyo to correct it +without success. In Tokyo, an implementor reported that actual working +code ran over one page in length and was quite complicated. The LWG +decided that it would be counter-productive to include such a lengthy +example, which might well still contain errors.
+ + + + + +Section: 21.3.6.5 [string::erase] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [string::erase].
+View all issues with TC status.
+Discussion:
+The string::erase(iterator first, iterator last) is specified to return an element one +place beyond the next element after the last one erased. E.g. for the string +"abcde", erasing the range ['b'..'d') would yield an iterator for element 'e', +while 'd' has not been erased.
+ + +Proposed resolution:
+In 21.3.6.5 [string::erase], paragraph 10, change:
+ +++ +Returns: an iterator which points to the element immediately following _last_ prior to + the element being erased.
+
to read
+ +++ + + + + +Returns: an iterator which points to the element pointed to by _last_ prior to the + other elements being erased.
+
Section: 22.2.1.3.2 [facet.ctype.char.members] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [facet.ctype.char.members].
+View all issues with TC status.
+Duplicate of: 236
+Discussion:
+The description of the vector form of ctype<char>::is can be interpreted to mean +something very different from what was intended. Paragraph 4 says
+ +++ +Effects: The second form, for all *p in the range [low, high), assigns vec[p-low] to + table()[(unsigned char)*p].
+
This is intended to copy the value indexed from table()[] into the place identified in +vec[].
+ + +Proposed resolution:
+Change 22.2.1.3.2 [facet.ctype.char.members], paragraph 4, to read
+ +++ + + + + +Effects: The second form, for all *p in the range [low, high), assigns into vec[p-low] + the value table()[(unsigned char)*p].
+
Section: 27.3.1 [narrow.stream.objects] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [narrow.stream.objects].
+View all issues with TC status.
+Discussion:
+Sections 27.3.1 [narrow.stream.objects] and 27.3.2 [wide.stream.objects] mention +a function ios_base::init, which is not defined. Probably they mean +basic_ios<>::init, defined in 27.4.4.1 [basic.ios.cons], +paragraph 3.
+ + +Proposed resolution:
+[R12: modified to include paragraph 5.]
+ +In 27.3.1 [narrow.stream.objects] paragraph 2 and 5, change
+ +++ +ios_base::init
+
to
+ +++ +basic_ios<char>::init
+
Also, make a similar change in 27.3.2 [wide.stream.objects] except it +should read
+ +++ + + + + +basic_ios<wchar_t>::init
+
Section: 22.1.1.1.1 [locale.category] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale.category].
+View all issues with TC status.
+Discussion:
+Paragraph 2 implies that the C macros LC_CTYPE etc. are defined in <cctype>, +where they are in fact defined elsewhere to appear in <clocale>.
+ + +Proposed resolution:
+In 22.1.1.1.1 [locale.category], paragraph 2, change +"<cctype>" to read "<clocale>".
+ + + + + +Section: 22.1.1 [locale] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale].
+View all issues with TC status.
+Duplicate of: 378
+Discussion:
+Paragraph 6, says "An instance of locale is +immutable; once a facet reference is obtained from it, +...". This has caused some confusion, because locale variables +are manifestly assignable.
+ + +Proposed resolution:
+In 22.1.1 [locale] replace paragraph 6
+ +++ +An instance of locale is immutable; once a facet + reference is obtained from it, that reference remains usable as long + as the locale value itself exists.
+
with
+ +++ + + + + +Once a facet reference is obtained from a locale object by + calling use_facet<>, that reference remains usable, and the + results from member functions of it may be cached and re-used, as + long as some locale object refers to that facet.
+
Section: 27.5.2.4.4 [streambuf.virt.pback] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all issues with TC status.
+Discussion:
+The description of the required state before calling virtual member +basic_streambuf<>::pbackfail requirements is inconsistent with the conditions +described in 27.5.2.2.4 [lib.streambuf.pub.pback] where member sputbackc calls it. +Specifically, the latter says it calls pbackfail if:
+ +traits::eq(c,gptr()[-1]) is false
+ +where pbackfail claims to require:
+ +traits::eq(*gptr(),traits::to_char_type(c)) returns false
+ +It appears that the pbackfail description is wrong.
+ + +Proposed resolution:
+In 27.5.2.4.4 [streambuf.virt.pback], paragraph 1, change:
+ +++ +"traits::eq(*gptr(),traits::to_char_type( c))"
+
to
+ +++ + +"traits::eq(traits::to_char_type(c),gptr()[-1])" +
+
Rationale:
+Note deliberate reordering of arguments for clarity in addition to the correction of +the argument value.
+ + + + + +Section: 22.2.1.4 [locale.codecvt] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale.codecvt].
+View all issues with TC status.
+Duplicate of: 43
+Discussion:
+In the table defining the results from do_out and do_in, the specification for the +result error says
+ +++ +encountered a from_type character it could not convert
+
but from_type is not defined. This clearly is intended to be an externT for do_in, or +an internT for do_out.
+ + +Proposed resolution:
+In 22.2.1.4.2 [locale.codecvt.virtuals] paragraph 4, replace the definition +in the table for the case of _error_ with
+ +++ + + + + +encountered a character in [from,from_end) that it could not convert.
+
Section: 22.2.2.2.2 [facet.num.put.virtuals] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [facet.num.put.virtuals].
+View all issues with TC status.
+Discussion:
+In paragraph 19, Effects:, members truename() and falsename are used from facet +ctype<charT>, but it has no such members. Note that this is also a problem in +22.2.2.1.2, addressed in (4).
+ + +Proposed resolution:
+In 22.2.2.2.2 [facet.num.put.virtuals], paragraph 19, in the Effects: +clause for member put(...., bool), replace the initialization of the +string_type value s as follows:
+ +++ + + + + +const numpunct& np = use_facet<numpunct<charT> >(loc); +string_type s = val ? np.truename() : np.falsename();+
Section: 27.4 [iostreams.base] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all issues with TC status.
+Discussion:
+In 27.4.5.1 [fmtflags.manip], we have a definition for a manipulator +named "unitbuf". Unlike other manipulators, it's not listed +in synopsis. Similarly for "nounitbuf".
+ + +Proposed resolution:
+Add to the synopsis for <ios> in 27.4 [iostreams.base], after +the entry for "nouppercase", the prototypes:
+ +++ + + + + +ios_base& unitbuf(ios_base& str); +ios_base& nounitbuf(ios_base& str);+
Section: 27.4.2.5 [ios.base.storage] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [ios.base.storage].
+View all issues with TC status.
+Discussion:
+In the definitions for ios_base::iword and pword, the lifetime of the storage is +specified badly, so that an implementation which only keeps the last value stored appears +to conform. In particular, it says:
+ +The reference returned may become invalid after another call to the object's iword +member with a different index ...
+ +This is not idle speculation; at least one implementation was done this way.
+ + +Proposed resolution:
+Add in 27.4.2.5 [ios.base.storage], in both paragraph 2 and also in +paragraph 4, replace the sentence:
+ +++ +The reference returned may become invalid after another call to the object's iword + [pword] member with a different index, after a call to its copyfmt member, or when the + object is destroyed.
+
with:
+ +++ +The reference returned is invalid after any other operations on the object. However, + the value of the storage referred to is retained, so that until the next call to copyfmt, + calling iword [pword] with the same index yields another reference to the same value.
+
substituting "iword" or "pword" as appropriate.
+ + + + + +Section: 22.1.1 [locale] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [locale].
+View all issues with TC status.
+Discussion:
+In the overview of locale semantics, paragraph 4, is the sentence
+ +++ +If Facet is not present in a locale (or, failing that, in the global locale), it throws + the standard exception bad_cast.
+
This is not supported by the definition of use_facet<>, and represents semantics +from an old draft.
+ + +Proposed resolution:
+In 22.1.1 [locale], paragraph 4, delete the parenthesized +expression
+ +++ + + + + +(or, failing that, in the global locale)
+
Section: 22.1.2 [locale.global.templates] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all issues with TC status.
+Discussion:
+It has been noticed by Esa Pulkkinen that the definition of +"facet" is incomplete. In particular, a class derived from +another facet, but which does not define a member id, cannot +safely serve as the argument F to use_facet<F>(loc), +because there is no guarantee that a reference to the facet instance +stored in loc is safely convertible to F.
+ + +Proposed resolution:
+In the definition of std::use_facet<>(), replace the text in paragraph 1 which +reads:
+ +++ +Get a reference to a facet of a locale.
+
with:
+ +++ +Requires: Facet is a facet class whose definition + contains the public static member id as defined in 22.1.1.1.2 [locale.facet].
+
[ +Kona: strike as overspecification the text "(not inherits)" +from the original resolution, which read "... whose definition +contains (not inherits) the public static member +id..." +]
+ + + + + + + +Section: 24.5.3.4 [istreambuf.iterator::op++] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all issues with TC status.
+Discussion:
+Following the definition of istreambuf_iterator<>::operator++(int) in paragraph +3, the standard contains three lines of garbage text left over from a previous edit.
+ +++ + +istreambuf_iterator<charT,traits> tmp = *this; +sbuf_->sbumpc(); +return(tmp);+
Proposed resolution:
+In 24.5.3.4 [istreambuf.iterator::op++], delete the three lines of code at the +end of paragraph 3.
+ + + + + +Section: 22.2.8 [facets.examples] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [facets.examples].
+View all issues with TC status.
+Discussion:
+Paragraph 3 of the locale examples is a description of part of an +implementation technique that has lost its referent, and doesn't mean +anything.
+ + +Proposed resolution:
+Delete 22.2.8 [facets.examples] paragraph 3 which begins "This +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 [ios.base] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [ios.base].
+View all issues with TC status.
+Duplicate of: 157
+Discussion:
+The description of ios_base::iword() and pword() in 27.4.2.4 [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 +basic_ios<>.
+ + +Proposed resolution:
+Change the description in 27.4.2.5 [ios.base.storage] in +paragraph 2, and also in paragraph 4, as follows. Replace
+ +++ +If the function fails it sets badbit, which may throw an exception.
+
with
+ +++ +If the function fails, and *this is a base sub-object of + a basic_ios<> object or sub-object, the effect is + equivalent to calling basic_ios<>::setstate(badbit) + on the derived object (which may throw failure).
+
[Kona: LWG reviewed wording; setstate(failbit) changed to +setstate(badbit).]
+ + + + + + + +Section: 21.3 [basic.string] Status: TC + Submitter: Nathan Myers Date: 1998-08-06
+View other active issues in [basic.string].
+View all other issues in [basic.string].
+View all issues with TC status.
+Discussion:
+The basic_string<> copy constructor:
+ +basic_string(const basic_string& str, size_type pos = 0, + size_type n = npos, const Allocator& a = Allocator());+ +
specifies an Allocator argument default value that is +counter-intuitive. The natural choice for a the allocator to copy from +is str.get_allocator(). Though this cannot be expressed in +default-argument notation, overloading suffices.
+ +Alternatively, the other containers in Clause 23 (deque, list, +vector) do not have this form of constructor, so it is inconsistent, +and an evident source of confusion, for basic_string<> to have +it, so it might better be removed.
+ + +Proposed resolution:
+In 21.3 [basic.string], replace the declaration of the copy +constructor as follows:
+ +++ +basic_string(const basic_string& str); +basic_string(const basic_string& str, size_type pos, size_type n = npos, + const Allocator& a = Allocator());+
In 21.3.1 [string.require], replace the copy constructor declaration +as above. Add to paragraph 5, Effects:
+ +++ + +In the first form, the Allocator value used is copied from + str.get_allocator().
+
Rationale:
+The LWG believes the constructor is actually broken, rather than +just an unfortunate design choice.
+ +The LWG considered two other possible resolutions:
+ +A. In 21.3 [basic.string], replace the declaration of the copy +constructor as follows:
+ +++ +basic_string(const basic_string& str, size_type pos = 0, + size_type n = npos); +basic_string(const basic_string& str, size_type pos, + size_type n, const Allocator& a);+
In 21.3.1 [string.require], replace the copy constructor declaration +as above. Add to paragraph 5, Effects:
+ +++ +When no Allocator argument is provided, the string is constructed using the + value str.get_allocator().
+
B. In 21.3 [basic.string], and also in 21.3.1 [string.require], replace +the declaration of the copy constructor as follows:
+ +++ +basic_string(const basic_string& str, size_type pos = 0, + size_type n = npos);+
The proposed resolution reflects the original intent of the LWG. It +was also noted by Pete Becker that this fix "will cause +a small amount of existing code to now work correctly."
+ +[ +Kona: issue editing snafu fixed - the proposed resolution now correctly +reflects the LWG consensus. +]
+ + + + + + +Section: 27 [input.output] Status: WP + Submitter: Nathan Myers Date: 1998-08-06
+View all other issues in [input.output].
+View all issues with WP status.
+Discussion:
+Many of the specifications for iostreams specify that character +values or their int_type equivalents are compared using operators == +or !=, though in other places traits::eq() or traits::eq_int_type is +specified to be used throughout. This is an inconsistency; we should +change uses of == and != to use the traits members instead.
+ + +Proposed resolution:
+ +[Pre-Kona: Dietmar supplied wording]
+ + +List of changes to clause 27:
++ + to + +fillch == fill() +
+ + +traits::eq(fillch, fill()) +
+ + to + +c == delim for the next available input character c +
+ +traits::eq(c, delim) for the next available input character c +
+ + to + +c == delim for the next available input character c +
+ +traits::eq(c, delim) for the next available input character c +
+ + to + +c == delim for the next available input character c +
+ +traits::eq(c, delim) for the next available input character c +
+ + to + +c == delim for the next available input character c +
+ +traits::eq_int_type(c, delim) for the next available input + character c +
+ + to + +The last condition will never occur if delim == traits::eof() +
+ +The last condition will never occur if + traits::eq_int_type(delim, traits::eof()). +
+ + to + +while ((c = is.rdbuf()->snextc()) != traits::eof()) { +
+ +while (!traits::eq_int_type(c = is.rdbuf()->snextc(), traits::eof())) { +
List of changes to Chapter 21:
+ ++ + to + +at(xpos+I) == str.at(I) for all elements ... +
+ +traits::eq(at(xpos+I), str.at(I)) for all elements ... +
+ + to + +at(xpos+I) == str.at(I) for all elements ... +
+ +traits::eq(at(xpos+I), str.at(I)) for all elements ... +
+ + to + +at(xpos+I) == str.at(I) for all elements ... +
+ +traits::eq(at(xpos+I), str.at(I)) for all elements ... +
+ + to + +at(xpos+I) == str.at(I) for all elements ... +
+ +traits::eq(at(xpos+I), str.at(I)) for all elements ... +
+ + to + +at(xpos+I) == str.at(I) for all elements ... +
+traits::eq(at(xpos+I), str.at(I)) for all elements ... +
+ + to + +at(xpos+I) == str.at(I) for all elements ... +
+traits::eq(at(xpos+I), str.at(I)) for all elements ... +
+ + to + +c == delim for the next available input character c +
+traits::eq(c, delim) for the next available input character c +
Notes:
+Section: D.7 [depr.str.strstreams] Status: TC + Submitter: Brendan Kehoe Date: 1998-06-01
+View all issues with TC status.
+Discussion:
See lib-6522 and edit-814.
+ +Proposed resolution:
+Change D.7.1 [depr.strstreambuf] (since streambuf is a typedef of +basic_streambuf<char>) from:
+ +virtual streambuf<char>* setbuf(char* s, streamsize n);+ +
to:
+ +virtual streambuf* setbuf(char* s, streamsize n);+ +
In D.7.4 [depr.strstream] insert the semicolon now missing after +int_type:
+ +namespace std { + class strstream + : public basic_iostream<char> { + public: + // Types + typedef char char_type; + typedef typename char_traits<char>::int_type int_type + typedef typename char_traits<char>::pos_type pos_type;+ + + + + +
Section: 27.4.2.3 [ios.base.locales] Status: TC + Submitter: Matt Austern Date: 1998-06-21
+View all other issues in [ios.base.locales].
+View all issues with TC status.
+Discussion:
+Section 27.4.2.3 specifies how imbue() and getloc() work. That +section has two RETURNS clauses, and they make no sense as +stated. They make perfect sense, though, if you swap them. Am I +correct in thinking that paragraphs 2 and 4 just got mixed up by +accident?
+ + +Proposed resolution:
+In 27.4.2.3 [ios.base.locales] swap paragraphs 2 and 4.
+ + + + + +Section: 27.4.2.1.1 [ios::failure] Status: TC + Submitter: Matt Austern Date: 1998-06-21
+View all other issues in [ios::failure].
+View all issues with TC status.
+Discussion:
+27.4.2.1.1, paragraph 2, says that class failure initializes the +base class, exception, with exception(msg). Class exception (see +18.6.1) has no such constructor.
+ + +Proposed resolution:
+Replace 27.4.2.1.1 [ios::failure], paragraph 2, with
+ +++ + + + + +EFFECTS: Constructs an object of class failure.
+
Section: 27.4.2.4 [ios.members.static] Status: WP + Submitter: Matt Austern Date: 1998-06-21
+View all issues with WP status.
+Discussion:
+Two problems
+ +(1) 27.4.2.4 doesn't say what ios_base::sync_with_stdio(f) +returns. Does it return f, or does it return the previous +synchronization state? My guess is the latter, but the standard +doesn't say so.
+ +(2) 27.4.2.4 doesn't say what it means for streams to be +synchronized with stdio. Again, of course, I can make some +guesses. (And I'm unhappy about the performance implications of those +guesses, but that's another matter.)
+ + +Proposed resolution:
+Change the following sentence in 27.4.2.4 [ios.members.static] +returns clause from:
+ +++ +true if the standard iostream objects (27.3) are + synchronized and otherwise returns false.
+
to:
+ +++ +true if the previous state of the standard iostream + objects (27.3) was synchronized and otherwise returns + false.
+
Add the following immediately after 27.4.2.4 [ios.members.static], +paragraph 2:
+ +++ +When a standard iostream object str is synchronized with a +standard stdio stream f, the effect of inserting a character c by
+fputc(f, c); ++ +is the same as the effect of
+str.rdbuf()->sputc(c); ++ +for any sequence of characters; the effect of extracting a +character c by
+c = fgetc(f); ++ +is the same as the effect of:
+c = str.rdbuf()->sbumpc(c); ++ +for any sequences of characters; and the effect of pushing +back a character c by
+ungetc(c, f); ++ +is the same as the effect of
+str.rdbuf()->sputbackc(c); ++ +for any sequence of characters. [Footnote: This implies +that operations on a standard iostream object can be mixed arbitrarily +with operations on the corresponding stdio stream. In practical +terms, synchronization usually means that a standard iostream object +and a standard stdio object share a buffer. --End Footnote]
+
[pre-Copenhagen: PJP and Matt contributed the definition +of "synchronization"]
+ + +[post-Copenhagen: proposed resolution was revised slightly: +text was added in the non-normative footnote to say that operations +on the two streams can be mixed arbitrarily.]
+ + + + + + +Section: 27.4.2 [ios.base] Status: TC + Submitter: Matt Austern Date: 1998-06-21
+View all other issues in [ios.base].
+View all issues with TC status.
+Discussion:
+As written, ios_base has a copy constructor and an assignment +operator. (Nothing in the standard says it doesn't have one, and all +classes have copy constructors and assignment operators unless you +take specific steps to avoid them.) However, nothing in 27.4.2 says +what the copy constructor and assignment operator do.
+ +My guess is that this was an oversight, that ios_base is, like +basic_ios, not supposed to have a copy constructor or an assignment +operator.
+ ++Jerry Schwarz comments: Yes, its an oversight, but in the opposite +sense to what you're suggesting. At one point there was a definite +intention that you could copy ios_base. It's an easy way to save the +entire state of a stream for future use. As you note, to carry out +that intention would have required a explicit description of the +semantics (e.g. what happens to the iarray and parray stuff). +
+ + +Proposed resolution:
+In 27.4.2 [ios.base], class ios_base, specify the copy +constructor and operator= members as being private.
+ + +Rationale:
+The LWG believes the difficulty of specifying correct semantics +outweighs any benefit of allowing ios_base objects to be copyable.
+ + + + + +Section: 23.1 [container.requirements] Status: TC + Submitter: David Vandevoorde Date: 1998-06-23
+View other active issues in [container.requirements].
+View all other issues in [container.requirements].
+View all issues with TC status.
+Discussion:
+The std::sort algorithm can in general only sort a given sequence +by moving around values. The list<>::sort() member on the other +hand could move around values or just update internal pointers. Either +method can leave iterators into the list<> dereferencable, but +they would point to different things.
+ +Does the FDIS mandate anywhere which method should be used for +list<>::sort()?
+ +Matt Austern comments:
+ +I think you've found an omission in the standard.
+ +The library working group discussed this point, and there was +supposed to be a general requirement saying that list, set, map, +multiset, and multimap may not invalidate iterators, or change the +values that iterators point to, except when an operation does it +explicitly. So, for example, insert() doesn't invalidate any iterators +and erase() and remove() only invalidate iterators pointing to the +elements that are being erased.
+ +I looked for that general requirement in the FDIS, and, while I +found a limited form of it for the sorted associative containers, I +didn't find it for list. It looks like it just got omitted.
+ +The intention, though, is that list<>::sort does not +invalidate any iterators and does not change the values that any +iterator points to. There would be no reason to have the member +function otherwise.
+ + +Proposed resolution:
+Add a new paragraph at the end of 23.1:
+ +++ + +Unless otherwise specified (either explicitly or by defining a function in terms of + other functions), invoking a container member function or passing a container as an + argument to a library function shall not invalidate iterators to, or change the values of, + objects within that container.
+
Rationale:
+This was US issue CD2-23-011; it was accepted in London but the +change was not made due to an editing oversight. The wording in the +proposed resolution below is somewhat updated from CD2-23-011, +particularly the addition of the phrase "or change the values +of"
+ + + + + +Section: 27.4.3.2 [fpos.operations] Status: TC + Submitter: Matt Austern Date: 1998-06-23
+View all issues with TC status.
+Discussion:
+First, 27.4.4.1 [basic.ios.cons], table 89. This is pretty obvious: +it should be titled "basic_ios<>() effects", not +"ios_base() effects".
+ +[The second item is a duplicate; see issue 6 for +resolution.]
+ +Second, 27.4.3.2 [fpos.operations] table 88 . There are a couple +different things wrong with it, some of which I've already discussed +with Jerry, but the most obvious mechanical sort of error is that it +uses expressions like P(i) and p(i), without ever defining what sort +of thing "i" is. +
+ +(The other problem is that it requires support for streampos +arithmetic. This is impossible on some systems, i.e. ones where file +position is a complicated structure rather than just a number. Jerry +tells me that the intention was to require syntactic support for +streampos arithmetic, but that it wasn't actually supposed to do +anything meaningful except on platforms, like Unix, where genuine +arithmetic is possible.)
+ + +Proposed resolution:
+Change 27.4.4.1 [basic.ios.cons] table 89 title from +"ios_base() effects" to "basic_ios<>() +effects".
+ + + + + +Section: 27.4.4.1 [basic.ios.cons] Status: TC + Submitter: Matt Austern Date: 1998-06-23
+View all other issues in [basic.ios.cons].
+View all issues with TC status.
+Discussion:
+There's nothing in 27.4.4 saying what basic_ios's destructor does. +The important question is whether basic_ios::~basic_ios() destroys +rdbuf().
+ + +Proposed resolution:
+Add after 27.4.4.1 [basic.ios.cons] paragraph 2:
+ +++ + +virtual ~basic_ios();
+Notes: The destructor does not destroy rdbuf().
+
Rationale:
+The LWG reviewed the additional question of whether or not +rdbuf(0) may set badbit. The answer is +clearly yes; it may be set via clear(). See 27.4.4.2 [basic.ios.members], paragraph 6. This issue was reviewed at length +by the LWG, which removed from the original proposed resolution a +footnote which incorrectly said "rdbuf(0) does not set +badbit".
+ + + + + +Section: 27.5.2.1 [streambuf.cons] Status: TC + Submitter: Matt Austern Date: 1998-06-25
+View all other issues in [streambuf.cons].
+View all issues with TC status.
+Discussion:
+The class synopsis for basic_streambuf shows a (virtual) +destructor, but the standard doesn't say what that destructor does. My +assumption is that it does nothing, but the standard should say so +explicitly.
+ + +Proposed resolution:
+Add after 27.5.2.1 [streambuf.cons] paragraph 2:
+ +++ + + + + +virtual ~basic_streambuf();
+Effects: None.
+
Section: 27 [input.output] Status: TC + Submitter: Matt Austern Date: 1998-06-26
+View all other issues in [input.output].
+View all issues with TC status.
+Discussion:
+Several member functions in clause 27 are defined in certain +circumstances to return an "invalid stream position", a term +that is defined nowhere in the standard. Two places (27.5.2.4.2, +paragraph 4, and 27.8.1.4, paragraph 15) contain a cross-reference to +a definition in _lib.iostreams.definitions_, a nonexistent +section.
+ +I suspect that the invalid stream position is just supposed to be +pos_type(-1). Probably best to say explicitly in (for example) +27.5.2.4.2 that the return value is pos_type(-1), rather than to use +the term "invalid stream position", define that term +somewhere, and then put in a cross-reference.
+ +The phrase "invalid stream position" appears ten times in +the C++ Standard. In seven places it refers to a return value, and it +should be changed. In three places it refers to an argument, and it +should not be changed. Here are the three places where "invalid +stream position" should not be changed:
+ +++ + +27.7.1.4 [stringbuf.virtuals], paragraph 14
+
+ 27.8.1.5 [filebuf.virtuals], paragraph 14
+ D.7.1.3 [depr.strstreambuf.virtuals], paragraph 17 +
Proposed resolution:
+In 27.5.2.4.2 [streambuf.virt.buffer], paragraph 4, change "Returns an +object of class pos_type that stores an invalid stream position +(_lib.iostreams.definitions_)" to "Returns +pos_type(off_type(-1))". +
+ +In 27.5.2.4.2 [streambuf.virt.buffer], paragraph 6, change "Returns +an object of class pos_type that stores an invalid stream +position" to "Returns pos_type(off_type(-1))".
+ +In 27.7.1.4 [stringbuf.virtuals], paragraph 13, change "the object +stores an invalid stream position" to "the return value is +pos_type(off_type(-1))".
+ +In 27.8.1.5 [filebuf.virtuals], paragraph 13, change "returns an +invalid stream position (27.4.3)" to "returns +pos_type(off_type(-1))"
+ +In 27.8.1.5 [filebuf.virtuals], paragraph 15, change "Otherwise +returns an invalid stream position (_lib.iostreams.definitions_)" +to "Otherwise returns pos_type(off_type(-1))" +
+ +In D.7.1.3 [depr.strstreambuf.virtuals], paragraph 15, change "the object +stores an invalid stream position" to "the return value is +pos_type(off_type(-1))"
+ +In D.7.1.3 [depr.strstreambuf.virtuals], paragraph 18, change "the object +stores an invalid stream position" to "the return value is +pos_type(off_type(-1))"
+ + + + + +Section: 27.5.2 [streambuf] Status: TC + Submitter: Matt Austern Date: 1998-06-29
+View all other issues in [streambuf].
+View all issues with TC status.
+Discussion:
+The class summary for basic_streambuf<>, in 27.5.2, says that +showmanyc has return type int. However, 27.5.2.4.3 says that its +return type is streamsize.
+ + +Proposed resolution:
+Change showmanyc's return type in the +27.5.2 [streambuf] class summary to streamsize.
+ + + + + +Section: 21.1.3.4 [char.traits.specializations.wchar.t] Status: TC + Submitter: Matt Austern Date: 1998-07-01
+View all issues with TC status.
+Discussion:
+21.1.3.2, paragraph 3, says "The types streampos and +wstreampos may be different if the implementation supports no shift +encoding in narrow-oriented iostreams but supports one or more shift +encodings in wide-oriented streams".
+ +That's wrong: the two are the same type. The <iosfwd> summary +in 27.2 says that streampos and wstreampos are, respectively, synonyms +for fpos<char_traits<char>::state_type> and +fpos<char_traits<wchar_t>::state_type>, and, flipping back +to clause 21, we see in 21.1.3.1 and 21.1.3.2 that +char_traits<char>::state_type and +char_traits<wchar_t>::state_type must both be mbstate_t.
+ + +Proposed resolution:
+Remove the sentence in 21.1.3.4 [char.traits.specializations.wchar.t] paragraph 3 which +begins "The types streampos and wstreampos may be +different..." .
+ + + + + +Section: 27.5.2.3.2 [streambuf.get.area] Status: TC + Submitter: Matt Austern Date: 1998-07-28
+View all issues with TC status.
+Discussion:
+27.5.2.3.1 says that basic_streambuf::gbump() "Advances the +next pointer for the input sequence by n."
+ +The straightforward interpretation is that it is just gptr() += +n. An alternative interpretation, though, is that it behaves as if it +calls sbumpc n times. (The issue, of course, is whether it might ever +call underflow.) There is a similar ambiguity in the case of +pbump.
+ +(The "classic" AT&T implementation used the +former interpretation.)
+ + +Proposed resolution:
+Change 27.5.2.3.2 [streambuf.get.area] paragraph 4 gbump effects from:
+ +++ +Effects: Advances the next pointer for the input sequence by n.
+
to:
+ +++ +Effects: Adds n to the next pointer for the input sequence.
+
Make the same change to 27.5.2.3.3 [streambuf.put.area] paragraph 4 pbump +effects.
+ + + + + +Section: 27.6.1.2.1 [istream.formatted.reqmts] Status: TC + Submitter: Matt Austern Date: 1998-08-03
+View all other issues in [istream.formatted.reqmts].
+View all issues with TC status.
+ +Discussion:
+Paragraph 1 of 27.6.1.2.1 contains general requirements for all +formatted input functions. Some of the functions defined in section +27.6.1.2 explicitly say that those requirements apply ("Behaves +like a formatted input member (as described in 27.6.1.2.1)"), but +others don't. The question: is 27.6.1.2.1 supposed to apply to +everything in 27.6.1.2, or only to those member functions that +explicitly say "behaves like a formatted input member"? Or +to put it differently: are we to assume that everything that appears +in a section called "Formatted input functions" really is a +formatted input function? I assume that 27.6.1.2.1 is intended to +apply to the arithmetic extractors (27.6.1.2.2), but I assume that it +is not intended to apply to extractors like
+ +basic_istream& operator>>(basic_istream& (*pf)(basic_istream&));+ +
and
+ +basic_istream& operator>>(basic_streammbuf*);+ +
There is a similar ambiguity for unformatted input, formatted output, and unformatted +output.
+ +Comments from Judy Ward: It seems like the problem is that the +basic_istream and basic_ostream operator <<()'s that are used +for the manipulators and streambuf* are in the wrong section and +should have their own separate section or be modified to make it clear +that the "Common requirements" listed in section 27.6.1.2.1 +(for basic_istream) and section 27.6.2.5.1 (for basic_ostream) do not +apply to them.
+ +Additional comments from Dietmar Kühl: It appears to be somewhat +nonsensical to consider the functions defined in 27.6.1.2.3 +[istream::extractors] paragraphs 1 to 5 to be "Formatted input +function" but since these functions are defined in a section +labeled "Formatted input functions" it is unclear to me +whether these operators are considered formatted input functions which +have to conform to the "common requirements" from 27.6.1.2.1 +[istream.formatted.reqmts]: If this is the case, all manipulators, not +just ws, would skip whitespace unless noskipws is +set (... but setting noskipws using the manipulator syntax +would also skip whitespace :-)
It is not clear which functions +are to be considered unformatted input functions. As written, it seems +that all functions in 27.6.1.3 [istream.unformatted] are unformatted input +functions. However, it does not really make much sense to construct a +sentry object for gcount(), sync(), ... Also it is +unclear what happens to the gcount() if +eg. gcount(), putback(), unget(), or +sync() is called: These functions don't extract characters, +some of them even "unextract" a character. Should this still +be reflected in gcount()? Of course, it could be read as if +after a call to gcount() gcount() return 0 +(the last unformatted input function, gcount(), didn't +extract any character) and after a call to putback() +gcount() returns -1 (the last unformatted input +function putback() did "extract" back into the +stream). Correspondingly for unget(). Is this what is +intended? If so, this should be clarified. Otherwise, a corresponding +clarification should be used.
+ + +Proposed resolution:
++In 27.6.1.2.2 [lib.istream.formatted.arithmetic], paragraph 1. +Change the beginning of the second sentence from "The conversion +occurs" to "These extractors behave as formatted input functions (as +described in 27.6.1.2.1). After a sentry object is constructed, +the conversion occurs" +
+ ++In 27.6.1.2.3, [lib.istream::extractors], before paragraph 1. +Add an effects clause. "Effects: None. This extractor does +not behave as a formatted input function (as described in +27.6.1.2.1). +
+ ++In 27.6.1.2.3, [lib.istream::extractors], paragraph 2. Change the +effects clause to "Effects: Calls pf(*this). This extractor does not +behave as a formatted input function (as described in 27.6.1.2.1). +
+ ++In 27.6.1.2.3, [lib.istream::extractors], paragraph 4. Change the +effects clause to "Effects: Calls pf(*this). This extractor does not +behave as a formatted input function (as described in 27.6.1.2.1). +
+ ++In 27.6.1.2.3, [lib.istream::extractors], paragraph 12. Change the +first two sentences from "If sb is null, calls setstate(failbit), +which may throw ios_base::failure (27.4.4.3). Extracts characters +from *this..." to "Behaves as a formatted input function (as described +in 27.6.1.2.1). If sb is null, calls setstate(failbit), which may +throw ios_base::failure (27.4.4.3). After a sentry object is +constructed, extracts characters from *this...". +
+ ++In 27.6.1.3, [lib.istream.unformatted], before paragraph 2. Add an +effects clause. "Effects: none. This member function does not behave +as an unformatted input function (as described in 27.6.1.3, paragraph 1)." +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 3. Change the +beginning of the first sentence of the effects clause from "Extracts a +character" to "Behaves as an unformatted input function (as described +in 27.6.1.3, paragraph 1). After constructing a sentry object, extracts a +character" +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 5. Change the +beginning of the first sentence of the effects clause from "Extracts a +character" to "Behaves as an unformatted input function (as described +in 27.6.1.3, paragraph 1). After constructing a sentry object, extracts a +character" +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 7. Change the +beginning of the first sentence of the effects clause from "Extracts +characters" to "Behaves as an unformatted input function (as described +in 27.6.1.3, paragraph 1). After constructing a sentry object, extracts +characters" +
+ ++[No change needed in paragraph 10, because it refers to paragraph 7.] +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 12. Change the +beginning of the first sentence of the effects clause from "Extracts +characters" to "Behaves as an unformatted input function (as described +in 27.6.1.3, paragraph 1). After constructing a sentry object, extracts +characters" +
+ ++[No change needed in paragraph 15.] +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 17. Change the +beginning of the first sentence of the effects clause from "Extracts +characters" to "Behaves as an unformatted input function (as described +in 27.6.1.3, paragraph 1). After constructing a sentry object, extracts +characters" +
+ ++[No change needed in paragraph 23.] +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 24. Change the +beginning of the first sentence of the effects clause from "Extracts +characters" to "Behaves as an unformatted input function (as described +in 27.6.1.3, paragraph 1). After constructing a sentry object, extracts +characters" +
+ ++In 27.6.1.3, [lib.istream.unformatted], before paragraph 27. Add an +Effects clause: "Effects: Behaves as an unformatted input function (as +described in 27.6.1.3, paragraph 1). After constructing a sentry +object, reads but does not extract the current input character." +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 28. Change the +first sentence of the Effects clause from "If !good() calls" to +Behaves as an unformatted input function (as described in 27.6.1.3, +paragraph 1). After constructing a sentry object, if !good() calls" +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 30. Change the +first sentence of the Effects clause from "If !good() calls" to +"Behaves as an unformatted input function (as described in 27.6.1.3, +paragraph 1). After constructing a sentry object, if !good() calls" +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 32. Change the +first sentence of the Effects clause from "If !good() calls..." to +"Behaves as an unformatted input function (as described in 27.6.1.3, +paragraph 1). After constructing a sentry object, if !good() +calls..." Add a new sentence to the end of the Effects clause: +"[Note: this function extracts no characters, so the value returned +by the next call to gcount() is 0.]" +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 34. Change the +first sentence of the Effects clause from "If !good() calls" to +"Behaves as an unformatted input function (as described in 27.6.1.3, +paragraph 1). After constructing a sentry object, if !good() calls". +Add a new sentence to the end of the Effects clause: "[Note: this +function extracts no characters, so the value returned by the next +call to gcount() is 0.]" +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 36. Change the +first sentence of the Effects clause from "If !rdbuf() is" to "Behaves +as an unformatted input function (as described in 27.6.1.3, paragraph +1), except that it does not count the number of characters extracted +and does not affect the value returned by subsequent calls to +gcount(). After constructing a sentry object, if rdbuf() is" +
+ ++In 27.6.1.3, [lib.istream.unformatted], before paragraph 37. Add an +Effects clause: "Effects: Behaves as an unformatted input function (as +described in 27.6.1.3, paragraph 1), except that it does not count the +number of characters extracted and does not affect the value returned +by subsequent calls to gcount()." Change the first sentence of +paragraph 37 from "if fail()" to "after constructing a sentry object, +if fail()". +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 38. Change the +first sentence of the Effects clause from "If fail()" to "Behaves +as an unformatted input function (as described in 27.6.1.3, paragraph +1), except that it does not count the number of characters extracted +and does not affect the value returned by subsequent calls to +gcount(). After constructing a sentry object, if fail() +
+ ++In 27.6.1.3, [lib.istream.unformatted], paragraph 40. Change the +first sentence of the Effects clause from "If fail()" to "Behaves +as an unformatted input function (as described in 27.6.1.3, paragraph +1), except that it does not count the number of characters extracted +and does not affect the value returned by subsequent calls to +gcount(). After constructing a sentry object, if fail() +
+ ++In 27.6.2.5.2 [lib.ostream.inserters.arithmetic], paragraph 1. Change +the beginning of the third sentence from "The formatting conversion" +to "These extractors behave as formatted output functions (as +described in 27.6.2.5.1). After the sentry object is constructed, the +conversion occurs". +
+ ++In 27.6.2.5.3 [lib.ostream.inserters], before paragraph 1. Add an +effects clause: "Effects: None. Does not behave as a formatted output +function (as described in 27.6.2.5.1).". +
+ ++In 27.6.2.5.3 [lib.ostream.inserters], paragraph 2. Change the +effects clause to "Effects: calls pf(*this). This extractor does not +behave as a formatted output function (as described in 27.6.2.5.1).". +
+ ++In 27.6.2.5.3 [lib.ostream.inserters], paragraph 4. Change the +effects clause to "Effects: calls pf(*this). This extractor does not +behave as a formatted output function (as described in 27.6.2.5.1).". +
+ ++In 27.6.2.5.3 [lib.ostream.inserters], paragraph 6. Change the first +sentence from "If sb" to "Behaves as a formatted output function (as +described in 27.6.2.5.1). After the sentry object is constructed, if +sb". +
+ ++In 27.6.2.6 [lib.ostream.unformatted], paragraph 2. Change the first +sentence from "Inserts the character" to "Behaves as an unformatted +output function (as described in 27.6.2.6, paragraph 1). After +constructing a sentry object, inserts the character". +
+ ++In 27.6.2.6 [lib.ostream.unformatted], paragraph 5. Change the first +sentence from "Obtains characters" to "Behaves as an unformatted +output function (as described in 27.6.2.6, paragraph 1). After +constructing a sentry object, obtains characters". +
+ ++In 27.6.2.6 [lib.ostream.unformatted], paragraph 7. Add a new +sentence at the end of the paragraph: "Does not behave as an +unformatted output function (as described in 27.6.2.6, paragraph 1)." +
+ + +Rationale:
+See J16/99-0043==WG21/N1219, Proposed Resolution to Library Issue 60, +by Judy Ward and Matt Austern. This proposed resolution is section +VI of that paper.
+ + + + + +Section: 27.6.1.3 [istream.unformatted] Status: TC + Submitter: Matt Austern Date: 1998-08-06
+View all other issues in [istream.unformatted].
+View all issues with TC status.
+Discussion:
+The introduction to the section on unformatted input (27.6.1.3) +says that every unformatted input function catches all exceptions that +were thrown during input, sets badbit, and then conditionally rethrows +the exception. That seems clear enough. Several of the specific +functions, however, such as get() and read(), are documented in some +circumstances as setting eofbit and/or failbit. (The standard notes, +correctly, that setting eofbit or failbit can sometimes result in an +exception being thrown.) The question: if one of these functions +throws an exception triggered by setting failbit, is this an exception +"thrown during input" and hence covered by 27.6.1.3, or does +27.6.1.3 only refer to a limited class of exceptions? Just to make +this concrete, suppose you have the following snippet.
+ ++ char buffer[N]; + istream is; + ... + is.exceptions(istream::failbit); // Throw on failbit but not on badbit. + is.read(buffer, N);+ +
Now suppose we reach EOF before we've read N characters. What +iostate bits can we expect to be set, and what exception (if any) will +be thrown?
+ + +Proposed resolution:
++In 27.6.1.3, paragraph 1, after the sentence that begins +"If an exception is thrown...", add the following +parenthetical comment: "(Exceptions thrown from +basic_ios<>::clear() are not caught or rethrown.)" +
+ + +Rationale:
+The LWG looked to two alternative wordings, and choose the proposed +resolution as better standardese.
+ + + + + +Section: 27.6.1.3 [istream.unformatted] Status: TC + Submitter: Matt Austern Date: 1998-08-06
+View all other issues in [istream.unformatted].
+View all issues with TC status.
+Discussion:
+The Effects clause for sync() (27.6.1.3, paragraph 36) says that it +"calls rdbuf()->pubsync() and, if that function returns -1 +... returns traits::eof()."
+ +That looks suspicious, because traits::eof() is of type +traits::int_type while the return type of sync() is int.
+ + +Proposed resolution:
+In 27.6.1.3 [istream.unformatted], paragraph 36, change "returns +traits::eof()" to "returns -1". +
+ + + + + +Section: 27.6.2.7 [ostream.unformatted] Status: TC + Submitter: Matt Austern Date: 1998-08-11
+View all other issues in [ostream.unformatted].
+View all issues with TC status.
+Discussion:
+Clause 27 details an exception-handling policy for formatted input, +unformatted input, and formatted output. It says nothing for +unformatted output (27.6.2.6). 27.6.2.6 should either include the same +kind of exception-handling policy as in the other three places, or +else it should have a footnote saying that the omission is +deliberate.
+ + +Proposed resolution:
++In 27.6.2.6, paragraph 1, replace the last sentence ("In any +case, the unformatted output function ends by destroying the sentry +object, then returning the value specified for the formatted output +function.") with the following text: +
++ + ++If an exception is thrown during output, then ios::badbit is +turned on [Footnote: without causing an ios::failure to be +thrown.] in *this's error state. If (exceptions() & +badbit) != 0 then the exception is rethrown. In any case, the +unformatted output function ends by destroying the sentry object, +then, if no exception was thrown, returning the value specified for +the formatted output function. +
Rationale:
++This exception-handling policy is consistent with that of formatted +input, unformatted input, and formatted output. +
+ + + + + +Section: 27.6.1.2.3 [istream::extractors] Status: TC + Submitter: Matt Austern Date: 1998-08-11
+View all other issues in [istream::extractors].
+View all issues with TC status.
+Discussion:
+27.6.1.2.3, paragraph 13, is ambiguous. It can be interpreted two +different ways, depending on whether the second sentence is read as an +elaboration of the first.
+ + +Proposed resolution:
+Replace 27.6.1.2.3 [istream::extractors], paragraph 13, which begins +"If the function inserts no characters ..." with:
+ +++ + + + + +If the function inserts no characters, it calls + setstate(failbit), which may throw + ios_base::failure (27.4.4.3). If it inserted no characters + because it caught an exception thrown while extracting characters + from sb and failbit is on in exceptions() + (27.4.4.3), then the caught exception is rethrown.
+
Section: D.7.1.3 [depr.strstreambuf.virtuals] Status: TC + Submitter: Matt Austern Date: 1998-08-18
+View all other issues in [depr.strstreambuf.virtuals].
+View all issues with TC status.
+Discussion:
+D.7.1.3, paragraph 19, says that strstreambuf::setbuf +"Performs an operation that is defined separately for each class +derived from strstreambuf". This is obviously an incorrect +cut-and-paste from basic_streambuf. There are no classes derived from +strstreambuf.
+ + +Proposed resolution:
+D.7.1.3 [depr.strstreambuf.virtuals], paragraph 19, replace the setbuf effects +clause which currently says "Performs an operation that is +defined separately for each class derived from strstreambuf" +with:
+ +++ + + + + +Effects: implementation defined, except that + setbuf(0,0) has no effect.
+
Section: 27.6.1.2.3 [istream::extractors] Status: TC + Submitter: Angelika Langer Date: 1998-07-14
+View all other issues in [istream::extractors].
+View all issues with TC status.
+Discussion:
+Extractors for char* (27.6.1.2.3) do not store a null character +after the extracted character sequence whereas the unformatted +functions like get() do. Why is this?
+ +Comment from Jerry Schwarz: There is apparently an editing +glitch. You'll notice that the last item of the list of what stops +extraction doesn't make any sense. It was supposed to be the line that +said a null is stored.
+ + +Proposed resolution:
+27.6.1.2.3 [istream::extractors], paragraph 7, change the last list +item from:
+ ++ ++ A null byte (charT()) in the next position, which may be + the first position if no characters were extracted. +
to become a new paragraph which reads:
+ ++ + + + + ++ Operator>> then stores a null byte (charT()) in the + next position, which may be the first position if no characters were + extracted. +
Section: 23.2.6 [vector] Status: TC + Submitter: Andrew Koenig Date: 1998-07-29
+View all other issues in [vector].
+View all issues with TC status.
+Discussion:
+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 +whether a vector iterator is required to be a pointer; the answer to +that question is clearly "no," as it would rule out +debugging implementations)
+ + +Proposed resolution:
+Add the following text to the end of 23.2.6 [vector], +paragraph 1.
+ +++ + +The elements of a vector are stored contiguously, meaning that if + v is a vector<T, Allocator> where T is some type + other than bool, then it obeys the identity &v[n] + == &v[0] + n for all 0 <= n < v.size().
+
Rationale:
+The LWG feels that as a practical matter the answer is clearly +"yes". There was considerable discussion as to the best way +to express the concept of "contiguous", which is not +directly defined in the standard. Discussion included:
+ +Section: 18.7 [support.exception], 18.7.4 [uncaught] Status: TC + Submitter: Steve Clamage Date: 1998-08-03
+View all other issues in [support.exception].
+View all issues with TC status.
+Discussion:
+In article 3E04@pratique.fr, Valentin Bonnard writes:
+ +uncaught_exception() doesn't have a throw specification.
+ +It is intentional ? Does it means that one should be prepared to +handle exceptions thrown from uncaught_exception() ?
+ +uncaught_exception() is called in exception handling contexts where +exception safety is very important.
+ + +Proposed resolution:
+In 15.5.3 [except.uncaught], paragraph 1, 18.7 [support.exception], +and 18.7.4 [uncaught], add "throw()" to uncaught_exception().
+ + + + +Section: 22.2.5.1 [locale.time.get] Status: TC + Submitter: Nathan Myers Date: 1998-08-13
+View all issues with TC status.
+Discussion:
+The locale facet member time_get<>::do_get_monthname +is described in 22.2.5.1.2 [locale.time.get.virtuals] with five arguments, +consistent with do_get_weekday and with its specified use by member +get_monthname. However, in the synopsis, it is specified instead with +four arguments. The missing argument is the "end" iterator +value.
+ + +Proposed resolution:
+In 22.2.5.1 [locale.time.get], add an "end" argument to +the declaration of member do_monthname as follows:
+ +virtual iter_type do_get_monthname(iter_type s, iter_type end, ios_base&, + ios_base::iostate& err, tm* t) const;+ + + + +
Section: 22.2.1.4 [locale.codecvt] Status: TC + Submitter: Matt Austern Date: 1998-09-08
+View all other issues in [locale.codecvt].
+View all issues with TC status.
+Discussion:
+The text of codecvt::do_max_length's "Returns" +clause (22.2.1.5.2, paragraph 11) is garbled. It has unbalanced +parentheses and a spurious n.
+ + +Proposed resolution:
+Replace 22.2.1.4.2 [locale.codecvt.virtuals] paragraph 11 with the +following:
+ ++ + + + ++ Returns: The maximum value that + do_length(state, from, from_end, 1) can return for any + valid range [from, from_end) and stateT value + state. The specialization codecvt<char, char, + mbstate_t>::do_max_length() returns 1. +
Section: 22.2.1.4 [locale.codecvt] Status: TC + Submitter: Matt +Austern Date: 1998-09-18
+View all other issues in [locale.codecvt].
+View all issues with TC status.
+Discussion:
+The class synopses for classes codecvt<> (22.2.1.5) +and codecvt_byname<> (22.2.1.6) say that the first +parameter of the member functions length and +do_length is of type const stateT&. The member +function descriptions, however (22.2.1.5.1, paragraph 6; 22.2.1.5.2, +paragraph 9) say that the type is stateT&. Either the +synopsis or the summary must be changed.
+ +If (as I believe) the member function descriptions are correct, +then we must also add text saying how do_length changes its +stateT argument.
+ + +Proposed resolution:
+In 22.2.1.4 [locale.codecvt], and also in 22.2.1.5 [locale.codecvt.byname], +change the stateT argument type on both member +length() and member do_length() from
+ +++ +const stateT&
+
to
+ +++ +stateT&
+
In 22.2.1.4.2 [locale.codecvt.virtuals], add to the definition for member +do_length a paragraph:
+ +++ + + + +Effects: The effect on the state argument is ``as if'' + it called do_in(state, from, from_end, from, to, to+max, + to) for to pointing to a buffer of at least + max elements.
+
Section: 22.2.1.4 [locale.codecvt] Status: WP + Submitter: Matt Austern Date: 1998-09-25
+View all other issues in [locale.codecvt].
+View all issues with WP status.
+Discussion:
+This issue concerns the requirements on classes derived from +codecvt, including user-defined classes. What are the +restrictions on the conversion from external characters +(e.g. char) to internal characters (e.g. wchar_t)? +Or, alternatively, what assumptions about codecvt facets can +the I/O library make?
+ +The question is whether it's possible to convert from internal +characters to external characters one internal character at a time, +and whether, given a valid sequence of external characters, it's +possible to pick off internal characters one at a time. Or, to put it +differently: given a sequence of external characters and the +corresponding sequence of internal characters, does a position in the +internal sequence correspond to some position in the external +sequence?
+ +To make this concrete, suppose that [first, last) is a +sequence of M external characters and that [ifirst, +ilast) is the corresponding sequence of N internal +characters, where N > 1. That is, my_encoding.in(), +applied to [first, last), yields [ifirst, +ilast). Now the question: does there necessarily exist a +subsequence of external characters, [first, last_1), such +that the corresponding sequence of internal characters is the single +character *ifirst? +
+ +(What a "no" answer would mean is that +my_encoding translates sequences only as blocks. There's a +sequence of M external characters that maps to a sequence of +N internal characters, but that external sequence has no +subsequence that maps to N-1 internal characters.)
+ +Some of the wording in the standard, such as the description of +codecvt::do_max_length (22.2.1.4.2 [locale.codecvt.virtuals], +paragraph 11) and basic_filebuf::underflow (27.8.1.5 [filebuf.virtuals], paragraph 3) suggests that it must always be +possible to pick off internal characters one at a time from a sequence +of external characters. However, this is never explicitly stated one +way or the other.
+ +This issue seems (and is) quite technical, but it is important if +we expect users to provide their own encoding facets. This is an area +where the standard library calls user-supplied code, so a well-defined +set of requirements for the user-supplied code is crucial. Users must +be aware of the assumptions that the library makes. This issue affects +positioning operations on basic_filebuf, unbuffered input, +and several of codecvt's member functions.
+ + +Proposed resolution:
+Add the following text as a new paragraph, following 22.2.1.4.2 [locale.codecvt.virtuals] paragraph 2:
+ +++ +A codecvt facet that is used by basic_filebuf +(27.8 [file.streams]) must have the property that if
+do_out(state, from, from_end, from_next, to, to_lim, to_next) ++would return ok, where from != from_end, then
+do_out(state, from, from + 1, from_next, to, to_end, to_next) ++must also return ok, and that if
+do_in(state, from, from_end, from_next, to, to_lim, to_next) ++would return ok, where to != to_lim, then
+do_in(state, from, from_end, from_next, to, to + 1, to_next) ++must also return ok. [Footnote: Informally, this +means that basic_filebuf assumes that the mapping from +internal to external characters is 1 to N: a codecvt that is +used by basic_filebuf must be able to translate characters +one internal character at a time. --End Footnote]
+
[Redmond: Minor change in proposed resolution. Original +proposed resolution talked about "success", with a parenthetical +comment that success meant returning ok. New wording +removes all talk about "success", and just talks about the +return value.]
+ + + + +Rationale:
+ +The proposed resoluion says that conversions can be performed one + internal character at a time. This rules out some encodings that + would otherwise be legal. The alternative answer would mean there + would be some internal positions that do not correspond to any + external file position.
++ An example of an encoding that this rules out is one where the + internT and externT are of the same type, and + where the internal sequence c1 c2 corresponds to the + external sequence c2 c1. +
+It was generally agreed that basic_filebuf relies + on this property: it was designed under the assumption that + the external-to-internal mapping is N-to-1, and it is not clear + that basic_filebuf is implementable without that + restriction. +
++ The proposed resolution is expressed as a restriction on + codecvt when used by basic_filebuf, rather + than a blanket restriction on all codecvt facets, + because basic_filebuf is the only other part of the + library that uses codecvt. If a user wants to define + a codecvt facet that implements a more general N-to-M + mapping, there is no reason to prohibit it, so long as the user + does not expect basic_filebuf to be able to use it. +
+ + + + + +Section: 27.4.2 [ios.base] Status: TC + Submitter: Nico Josuttis Date: 1998-09-29
+View all other issues in [ios.base].
+View all issues with TC status.
+Discussion:
+typo: event_call_back should be event_callback
+ + +Proposed resolution:
+In the 27.4.2 [ios.base] synopsis change +"event_call_back" to "event_callback".
+ + + + +Section: 26.3.1 [complex.synopsis], 26.3.7 [complex.value.ops] Status: TC + Submitter: Nico Josuttis Date: 1998-09-29
+View all other issues in [complex.synopsis].
+View all issues with TC status.
+Discussion:
+In 26.3.1 [complex.synopsis] polar is declared as follows:
+template<class T> complex<T> polar(const T&, const T&);+ +
In 26.3.7 [complex.value.ops] it is declared as follows:
+template<class T> complex<T> polar(const T& rho, const T& theta = 0);+ +
Thus whether the second parameter is optional is not clear.
+ + +Proposed resolution:
+In 26.3.1 [complex.synopsis] change:
+template<class T> complex<T> polar(const T&, const T&);+ +
to:
+template<class T> complex<T> polar(const T& rho, const T& theta = 0);+ + + + + +
Section: 26.3.1 [complex.synopsis], 26.3.2 [complex] Status: TC + Submitter: Nico Josuttis Date: 1998-09-29
+View all other issues in [complex.synopsis].
+View all issues with TC status.
+Discussion:
+Both 26.2.1 and 26.2.2 contain declarations of global operators for +class complex. This redundancy should be removed.
+ + +Proposed resolution:
+Reduce redundancy according to the general style of the standard.
+ + + + +Section: 21.3 [basic.string] Status: TC + Submitter: Nico Josuttis Date: 1998-09-29
+View other active issues in [basic.string].
+View all other issues in [basic.string].
+View all issues with TC status.
+Duplicate of: 89
+Discussion:
+Many string member functions throw if size is getting or exceeding +npos. However, I wonder why they don't throw if size is getting or +exceeding max_size() instead of npos. May be npos is known at compile +time, while max_size() is known at runtime. However, what happens if +size exceeds max_size() but not npos, then? It seems the standard +lacks some clarifications here.
+ + +Proposed resolution:
+After 21.3 [basic.string] paragraph 4 ("The functions +described in this clause...") add a new paragraph:
+ +++ + +For any string operation, if as a result of the operation, size() would exceed + max_size() then + the operation throws length_error.
+
Rationale:
+The LWG believes length_error is the correct exception to throw.
+ + + + +Section: 21.3.1 [string.require] Status: TC + Submitter: Nico Josuttis Date: 1998-09-29
+View all other issues in [string.require].
+View all issues with TC status.
+Discussion:
+The constructor from a range:
+ +template<class InputIterator> + basic_string(InputIterator begin, InputIterator end, + const Allocator& a = Allocator());+ +
lacks a throws clause. However, I would expect that it throws +according to the other constructors if the numbers of characters in +the range equals npos (or exceeds max_size(), see above).
+ + +Proposed resolution:
+In 21.3.1 [string.require], Strike throws paragraphs for +constructors which say "Throws: length_error if n == +npos."
+ + +Rationale:
+Throws clauses for length_error if n == npos are no longer needed +because they are subsumed by the general wording added by the +resolution for issue 83.
+ + + + +Section: 21.3.8.9 [string.io] Status: TC + Submitter: Nico Josuttis Date: 1998-09-29
+View all other issues in [string.io].
+View all issues with TC status.
+Discussion:
+The effect of operator >> for strings contain the following item:
+ +isspace(c,getloc()) is true for the next available input +character c.
+ +Here getloc() has to be replaced by is.getloc().
+ + +Proposed resolution:
+In 21.3.8.9 [string.io] paragraph 1 Effects clause replace:
+ +++ +isspace(c,getloc()) is true for the next available input character c.
+
with:
+ +++ + + + + +isspace(c,is.getloc()) is true for the next available input character c.
+
Section: 21.3.8.9 [string.io] Status: WP + Submitter: Nico Josuttis Date: 1998-09-29
+View all other issues in [string.io].
+View all issues with WP status.
+Discussion:
+Operator >> and getline() for strings read until eof() +in the input stream is true. However, this might never happen, if the +stream can't read anymore without reaching EOF. So shouldn't it be +changed into that it reads until !good() ?
+ + +Proposed resolution:
+In 21.3.8.9 [string.io], paragraph 1, replace:
+++Effects: Begins by constructing a sentry object k as if k were +constructed by typename basic_istream<charT,traits>::sentry k( is). If +bool( k) is true, it calls str.erase() and then extracts characters +from is and appends them to str as if by calling str.append(1, c). If +is.width() is greater than zero, the maximum number n of characters +appended is is.width(); otherwise n is str.max_size(). Characters are +extracted and appended until any of the following occurs: +
with:
++ ++Effects: Behaves as a formatted input function (27.6.1.2.1 +[istream.formatted.reqmts]). After constructing a sentry object, if the +sentry converts to true, calls str.erase() and then extracts +characters from is and appends them to str as if by calling +str.append(1,c). If is.width() is greater than zero, the maximum +number n of characters appended is is.width(); otherwise n is +str.max_size(). Characters are extracted and appended until any of the +following occurs: +
In 21.3.8.9 [string.io], paragraph 6, replace
+++Effects: Begins by constructing a sentry object k as if by typename +basic_istream<charT,traits>::sentry k( is, true). If bool( k) is true, +it calls str.erase() and then extracts characters from is and appends +them to str as if by calling str.append(1, c) until any of the +following occurs: +
with:
++ +Effects: Behaves as an unformatted input function +(27.6.1.3 [istream.unformatted]), except that it does not affect the +value returned +by subsequent calls to basic_istream<>::gcount(). After +constructing a sentry object, if the sentry converts to true, calls +str.erase() and then extracts characters from is and appends them to +str as if by calling str.append(1,c) until any of the following +occurs: +
[Redmond: Made changes in proposed resolution. operator>> +should be a formatted input function, not an unformatted input function. +getline should not be required to set gcount, since +there is no mechanism for gcount to be set except by one of +basic_istream's member functions.]
+ + +[Curaçao: Nico agrees with proposed resolution.]
+ + + + +Rationale:
+The real issue here is whether or not these string input functions +get their characters from a streambuf, rather than by calling an +istream's member functions, a streambuf signals failure either by +returning eof or by throwing an exception; there are no other +possibilities. The proposed resolution makes it clear that these two +functions do get characters from a streambuf.
+ + + + + +Section: 25 [algorithms] Status: WP + Submitter: Nico Josuttis Date: 1998-09-29
+View all other issues in [algorithms].
+View all issues with WP status.
+Discussion:
+The standard does not state, how often a function object is copied, +called, or the order of calls inside an algorithm. This may lead to +surprising/buggy behavior. Consider the following example:
+ +class Nth { // function object that returns true for the nth element + private: + int nth; // element to return true for + int count; // element counter + public: + Nth (int n) : nth(n), count(0) { + } + bool operator() (int) { + return ++count == nth; + } +}; +.... +// remove third element + list<int>::iterator pos; + pos = remove_if(coll.begin(),coll.end(), // range + Nth(3)), // remove criterion + coll.erase(pos,coll.end());+ +
This call, in fact removes the 3rd AND the 6th element. This +happens because the usual implementation of the algorithm copies the +function object internally:
+ +template <class ForwIter, class Predicate> +ForwIter std::remove_if(ForwIter beg, ForwIter end, Predicate op) +{ + beg = find_if(beg, end, op); + if (beg == end) { + return beg; + } + else { + ForwIter next = beg; + return remove_copy_if(++next, end, beg, op); + } +}+ +
The algorithm uses find_if() to find the first element that should +be removed. However, it then uses a copy of the passed function object +to process the resulting elements (if any). Here, Nth is used again +and removes also the sixth element. This behavior compromises the +advantage of function objects being able to have a state. Without any +cost it could be avoided (just implement it directly instead of +calling find_if()).
+ + +Proposed resolution:
+ +Add a new paragraph following 25 [algorithms] paragraph 8:
++ ++[Note: Unless otherwise specified, algorithms that take function +objects as arguments are permitted to copy those function objects +freely. Programmers for whom object identity is important should +consider using a wrapper class that points to a noncopied +implementation object, or some equivalent solution.] +
[Dublin: Pete Becker felt that this may not be a defect, +but rather something that programmers need to be educated about. +There was discussion of adding wording to the effect that the number +and order of calls to function objects, including predicates, not +affect the behavior of the function object.]
+ + +[Pre-Kona: Nico comments: It seems the problem is that we don't +have a clear statement of "predicate" in the +standard. People including me seemed to think "a function +returning a Boolean value and being able to be called by an STL +algorithm or be used as sorting criterion or ... is a +predicate". But a predicate has more requirements: It should +never change its behavior due to a call or being copied. IMHO we have +to state this in the standard. If you like, see section 8.1.4 of my +library book for a detailed discussion.]
+ + +[Kona: Nico will provide wording to the effect that "unless +otherwise specified, the number of copies of and calls to function +objects by algorithms is unspecified". Consider placing in +25 [algorithms] after paragraph 9.]
+ + +[Santa Cruz: The standard doesn't currently guarantee that + functions object won't be copied, and what isn't forbidden is + allowed. It is believed (especially since implementations that were + written in concert with the standard do make copies of function + objects) that this was intentional. Thus, no normative change is + needed. What we should put in is a non-normative note suggesting to + programmers that if they want to guarantee the lack of copying they + should use something like the ref wrapper.]
+ + +[Oxford: Matt provided wording.]
+ + + + + + + + +Section: 24.1.1 [input.iterators] Status: WP + Submitter: AFNOR Date: 1998-10-07
+View all other issues in [input.iterators].
+View all issues with WP status.
+Discussion:
+Table 72 in 24.1.1 [input.iterators] specifies semantics for +*r++ of:
+ +{ T tmp = *r; ++r; return tmp; }
+ +There are two problems with this. First, the return type is +specified to be "T", as opposed to something like "convertible to T". +This is too specific: we want to allow *r++ to return an lvalue.
+ +Second, writing the semantics in terms of code misleadingly +suggests that the effects *r++ should precisely replicate the behavior +of this code, including side effects. (Does this mean that *r++ +should invoke the copy constructor exactly as many times as the sample +code above would?) See issue 334 for a similar +problem.
+ + + +Proposed resolution:
+In Table 72 in 24.1.1 [input.iterators], change the return type +for *r++ from T to "convertible to T".
+ + +Rationale:
+This issue has two parts: the return type, and the number of times + the copy constructor is invoked.
+ +The LWG believes the the first part is a real issue. It's + inappropriate for the return type to be specified so much more + precisely for *r++ than it is for *r. In particular, if r is of + (say) type int*, then *r++ isn't int, + but int&.
+ +The LWG does not believe that the number of times the copy + constructor is invoked is a real issue. This can vary in any case, + because of language rules on copy constructor elision. That's too + much to read into these semantics clauses.
+ +Additionally, as Dave Abrahams pointed out (c++std-lib-13703): since + we're told (24.1/3) that forward iterators satisfy all the requirements + of input iterators, we can't impose any requirements in the Input + Iterator requirements table that forward iterators don't satisfy.
+ + + + + +Section: 23.1.4 [associative.reqmts] Status: WP + Submitter: AFNOR Date: 1998-10-07
+View all other issues in [associative.reqmts].
+View all issues with WP status.
+Discussion:
+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 +iterator pointing to T.
+ +23.1.2 paragraph 2 implies that the keys should not be modified to +break the ordering of elements. But that is not clearly +specified. Especially considering that the current standard requires +that iterator for associative containers be different from +const_iterator. Set, for example, has the following:
+ +typedef implementation defined iterator;
+ // See _lib.container.requirements_
23.1 [container.requirements] actually requires that iterator type pointing +to T (table 65). Disallowing user modification of keys by changing the +standard to require an iterator for associative container to be the +same as const_iterator would be overkill since that will unnecessarily +significantly restrict the usage of associative container. A class to +be used as elements of set, for example, can no longer be modified +easily without either redesigning the class (using mutable on fields +that have nothing to do with ordering), or using const_cast, which +defeats requiring iterator to be const_iterator. The proposed solution +goes in line with trusting user knows what he is doing.
+ +Other Options Evaluated:
+ +Option A. In 23.1.4 [associative.reqmts], paragraph 2, after +first sentence, and before "In addition,...", add one line: +
+ +++ +Modification of keys shall not change their strict weak ordering.
+
Option B. Add three new sentences to 23.1.4 [associative.reqmts]:
+ +++ +At the end of paragraph 5: "Keys in an associative container + are immutable." At the end of paragraph 6: "For + associative containers where the value type is the same as the key + type, both iterator and const_iterator are + constant iterators. It is unspecified whether or not + iterator and const_iterator are the same + type."
+
Option C. To 23.1.4 [associative.reqmts], paragraph 3, which +currently reads:
+ +++ +The phrase ``equivalence of keys'' means the equivalence relation imposed by the + comparison and not the operator== on keys. That is, two keys k1 and k2 in the same + container are considered to be equivalent if for the comparison object comp, comp(k1, k2) + == false && comp(k2, k1) == false.
+
add the following:
+ +++ + + +For any two keys k1 and k2 in the same container, comp(k1, k2) shall return the same + value whenever it is evaluated. [Note: If k2 is removed from the container and later + reinserted, comp(k1, k2) must still return a consistent value but this value may be + different than it was the first time k1 and k2 were in the same container. This is + intended to allow usage like a string key that contains a filename, where comp compares + file contents; if k2 is removed, the file is changed, and the same k2 (filename) is + reinserted, comp(k1, k2) must again return a consistent value but this value may be + different than it was the previous time k2 was in the container.]
+
Proposed resolution:
+Add the following to 23.1.4 [associative.reqmts] at +the indicated location:
+ +++ + +At the end of paragraph 3: "For any two keys k1 and k2 in the same container, + calling comp(k1, k2) shall always return the same + value."
+At the end of paragraph 5: "Keys in an associative container are immutable."
+At the end of paragraph 6: "For associative containers where the value type is the + same as the key type, both iterator and const_iterator are constant + iterators. It is unspecified whether or not iterator and const_iterator + are the same type."
+
Rationale:
+Several arguments were advanced for and against allowing set elements to be +mutable as long as the ordering was not effected. The argument which swayed the +LWG was one of safety; if elements were mutable, there would be no compile-time +way to detect of a simple user oversight which caused ordering to be +modified. There was a report that this had actually happened in practice, +and had been painful to diagnose. If users need to modify elements, +it is possible to use mutable members or const_cast.
+ +Simply requiring that keys be immutable is not sufficient, because the comparison +object may indirectly (via pointers) operate on values outside of the keys.
+ ++The types iterator and const_iterator are permitted +to be different types to allow for potential future work in which some +member functions might be overloaded between the two types. No such +member functions exist now, and the LWG believes that user functionality +will not be impaired by permitting the two types to be the same. A +function that operates on both iterator types can be defined for +const_iterator alone, and can rely on the automatic +conversion from iterator to const_iterator. +
+ +[Tokyo: The LWG crafted the proposed resolution and rationale.]
+ + + + + + +Section: 26.5.5 [template.slice.array] Status: TC + Submitter: AFNOR Date: 1998-10-07
+View all other issues in [template.slice.array].
+View all issues with TC status.
+Discussion:
+This is the only place in the whole standard where the implementation has to document +something private.
+ + +Proposed resolution:
++Remove the comment which says "// remainder implementation defined" from: +
+ +Section: 18.6.1 [type.info] Status: TC + Submitter: AFNOR Date: 1998-10-07
+View all other issues in [type.info].
+View all issues with TC status.
+Discussion:
+In 18.6.1, paragraphs 8-9, the lifetime of the return value of +exception::what() is left unspecified. This issue has implications +with exception safety of exception handling: some exceptions should +not throw bad_alloc.
+ + +Proposed resolution:
+Add to 18.6.1 [type.info] paragraph 9 (exception::what notes +clause) the sentence:
+ +++ + +The return value remains valid until the exception object from which it is obtained is + destroyed or a non-const member function of the exception object is called.
+
Rationale:
+If an exception object has non-const members, they may be used +to set internal state that should affect the contents of the string +returned by what(). +
+ + + + + +Section: D.8 [depr.lib.binders] Status: WP + Submitter: Bjarne Stroustrup Date: 1998-10-07
+View all other issues in [depr.lib.binders].
+View all issues with WP status.
+Discussion:
+ +There are no versions of binders that apply to non-const elements +of a sequence. This makes examples like for_each() using bind2nd() on +page 521 of "The C++ Programming Language (3rd)" +non-conforming. Suitable versions of the binders need to be added.
+ +Further discussion from Nico:
+ +What is probably meant here is shown in the following example:
+ +class Elem { + public: + void print (int i) const { } + void modify (int i) { } +};+
int main() +{ + vector<Elem> coll(2); + for_each (coll.begin(), coll.end(), bind2nd(mem_fun_ref(&Elem::print),42)); // OK + for_each (coll.begin(), coll.end(), bind2nd(mem_fun_ref(&Elem::modify),42)); // ERROR +}+ +
The error results from the fact that bind2nd() passes its first +argument (the argument of the sequence) as constant reference. See the +following typical implementation:
+ +++ +template <class Operation> +class binder2nd + : public unary_function<typename Operation::first_argument_type, + typename Operation::result_type> { +protected: + Operation op; + typename Operation::second_argument_type value; +public: + binder2nd(const Operation& o, + const typename Operation::second_argument_type& v) + : op(o), value(v) {}+typename Operation::result_type + operator()(const typename Operation::first_argument_type& x) const { + return op(x, value); + } +};+
The solution is to overload operator () of bind2nd for non-constant arguments:
+ +++ + +template <class Operation> +class binder2nd + : public unary_function<typename Operation::first_argument_type, + typename Operation::result_type> { +protected: + Operation op; + typename Operation::second_argument_type value; +public: + binder2nd(const Operation& o, + const typename Operation::second_argument_type& v) + : op(o), value(v) {}+typename Operation::result_type + operator()(const typename Operation::first_argument_type& x) const { + return op(x, value); + } + typename Operation::result_type + operator()(typename Operation::first_argument_type& x) const { + return op(x, value); + } +};+
Proposed resolution:
+ +Howard believes there is a flaw in this resolution. +See c++std-lib-9127. We may need to reopen this issue.
+ +In D.8 [depr.lib.binders] in the declaration of binder1st after:
+++typename Operation::result_type
+
+ operator()(const typename Operation::second_argument_type& x) const;
insert:
+++typename Operation::result_type
+
+ operator()(typename Operation::second_argument_type& x) const;
In D.8 [depr.lib.binders] in the declaration of binder2nd after:
+++typename Operation::result_type
+
+ operator()(const typename Operation::first_argument_type& x) const;
insert:
+++ +typename Operation::result_type
+
+ operator()(typename Operation::first_argument_type& x) const;
[Kona: The LWG discussed this at some length.It was agreed that +this is a mistake in the design, but there was no consensus on whether +it was a defect in the Standard. Straw vote: NAD - 5. Accept +proposed resolution - 3. Leave open - 6.]
+ + +[Copenhagen: It was generally agreed that this was a defect. +Strap poll: NAD - 0. Accept proposed resolution - 10. +Leave open - 1.]
+ + + + + + + +Section: 24.5.3 [istreambuf.iterator], 24.5.3.5 [istreambuf.iterator::equal] Status: TC + Submitter: Nathan Myers Date: 1998-10-15
+View all other issues in [istreambuf.iterator].
+View all issues with TC status.
+Discussion:
+Member istreambuf_iterator<>::equal is not declared +"const", yet 24.5.3.6 [istreambuf.iterator::op==] says that operator==, +which is const, calls it. This is contradictory.
+ + +Proposed resolution:
+In 24.5.3 [istreambuf.iterator] and also in 24.5.3.5 [istreambuf.iterator::equal], +replace:
+ +++ +bool equal(istreambuf_iterator& b);+
with:
+ +++ + + + + +bool equal(const istreambuf_iterator& b) const;+
Section: 24.5.4.1 [ostreambuf.iter.cons] Status: TC + Submitter: Matt Austern Date: 1998-10-20
+View all issues with TC status.
+Discussion:
+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 +reference, and references can't be null.
+ + +Proposed resolution:
+In 24.5.4.1 [ostreambuf.iter.cons]:
+ +Move the current paragraph 1, which reads "Requires: s is not +null.", from the first constructor to the second constructor.
+ +Insert a new paragraph 1 Requires clause for the first constructor +reading:
+ +++ + + + + +Requires: s.rdbuf() is not null.
+
Section: 18.5.1.3 [new.delete.placement] Status: TC + Submitter: Steve Clamage Date: 1998-10-28
+View all other issues in [new.delete.placement].
+View all issues with TC status.
+Duplicate of: 196
+Discussion:
+Section 18.5.1.3 contains the following example:
+ +[Example: This can be useful for constructing an object at a known address: + char place[sizeof(Something)]; + Something* p = new (place) Something(); + -end example]+ +
First code line: "place" need not have any special alignment, and the +following constructor could fail due to misaligned data.
+ +Second code line: Aren't the parens on Something() incorrect? [Dublin: the LWG +believes the () are correct.]
+ +Examples are not normative, but nevertheless should not show code that is invalid or +likely to fail.
+ + +Proposed resolution:
+Replace the first line of code in the example in +18.5.1.3 [new.delete.placement] with: +
+ +++ + + + + +void* place = operator new(sizeof(Something));+
Section: D.7.4.1 [depr.strstream.cons] Status: TC + Submitter: Steve Clamage Date: 1998-11-02
+View all issues with TC status.
+Discussion:
+D.7.4.1 strstream constructors paragraph 2 says:
+ +++ +Effects: Constructs an object of class strstream, initializing the base class with + iostream(& sb) and initializing sb with one of the two constructors:
+- If mode&app==0, then s shall designate the first element of an array of n + elements. The constructor is strstreambuf(s, n, s).
+- If mode&app==0, then s shall designate the first element of an array of n + elements that contains an NTBS whose first element is designated by s. The constructor is + strstreambuf(s, n, s+std::strlen(s)).
+
Notice the second condition is the same as the first. I think the second condition +should be "If mode&app==app", or "mode&app!=0", meaning that +the append bit is set.
+ + +Proposed resolution:
+In D.7.3.1 [depr.ostrstream.cons] paragraph 2 and D.7.4.1 [depr.strstream.cons] +paragraph 2, change the first condition to (mode&app)==0 +and the second condition to (mode&app)!=0.
+ + + + + +Section: 27.6.2.6.2 [ostream.inserters.arithmetic] Status: WP + Submitter: Matt Austern Date: 1998-11-20
+View all other issues in [ostream.inserters.arithmetic].
+View all issues with WP status.
+Discussion:
+The effects clause for numeric inserters says that +insertion of a value x, whose type is either bool, +short, unsigned short, int, unsigned +int, long, unsigned long, float, +double, long double, or const void*, is +delegated to num_put, and that insertion is performed as if +through the following code fragment:
+ +bool failed = use_facet< + num_put<charT,ostreambuf_iterator<charT,traits> > + >(getloc()).put(*this, *this, fill(), val). failed();+ +
This doesn't work, because num_put<>::put is only +overloaded for the types bool, long, unsigned +long, double, long double, and const +void*. That is, the code fragment in the standard is incorrect +(it is diagnosed as ambiguous at compile time) for the types +short, unsigned short, int, unsigned +int, and float.
+ +We must either add new member functions to num_put, or +else change the description in ostream so that it only calls +functions that are actually there. I prefer the latter.
+ + +Proposed resolution:
+Replace 27.6.2.5.2, paragraph 1 with the following:
+ +++ ++The classes num_get<> and num_put<> handle locale-dependent numeric +formatting and parsing. These inserter functions use the imbued +locale value to perform numeric formatting. When val is of type bool, +long, unsigned long, double, long double, or const void*, the +formatting conversion occurs as if it performed the following code +fragment: +
+ +bool failed = use_facet< + num_put<charT,ostreambuf_iterator<charT,traits> > + >(getloc()).put(*this, *this, fill(), val). failed(); ++ ++When val is of type short the formatting conversion occurs as if it +performed the following code fragment: +
+ +ios_base::fmtflags baseflags = ios_base::flags() & ios_base::basefield; +bool failed = use_facet< + num_put<charT,ostreambuf_iterator<charT,traits> > + >(getloc()).put(*this, *this, fill(), + baseflags == ios_base::oct || baseflags == ios_base::hex + ? static_cast<long>(static_cast<unsigned short>(val)) + : static_cast<long>(val)). failed(); ++ ++When val is of type int the formatting conversion occurs as if it performed +the following code fragment: +
+ +ios_base::fmtflags baseflags = ios_base::flags() & ios_base::basefield; +bool failed = use_facet< + num_put<charT,ostreambuf_iterator<charT,traits> > + >(getloc()).put(*this, *this, fill(), + baseflags == ios_base::oct || baseflags == ios_base::hex + ? static_cast<long>(static_cast<unsigned int>(val)) + : static_cast<long>(val)). failed(); ++ ++When val is of type unsigned short or unsigned int the formatting conversion +occurs as if it performed the following code fragment: +
+ +bool failed = use_facet< + num_put<charT,ostreambuf_iterator<charT,traits> > + >(getloc()).put(*this, *this, fill(), static_cast<unsigned long>(val)). +failed(); ++ ++When val is of type float the formatting conversion occurs as if it +performed the following code fragment: +
+ +bool failed = use_facet< + num_put<charT,ostreambuf_iterator<charT,traits> > + >(getloc()).put(*this, *this, fill(), static_cast<double>(val)). +failed(); ++ +
[post-Toronto: This differs from the previous proposed +resolution; PJP provided the new wording. The differences are in +signed short and int output.]
+ + + +Rationale:
+The original proposed resolution was to cast int and short to long, +unsigned int and unsigned short to unsigned long, and float to double, +thus ensuring that we don't try to use nonexistent num_put<> +member functions. The current proposed resolution is more +complicated, but gives more expected results for hex and octal output +of signed short and signed int. (On a system with 16-bit short, for +example, printing short(-1) in hex format should yield 0xffff.)
+ + + + + +Section: 27.6.1.2.2 [istream.formatted.arithmetic] Status: WP + Submitter: Matt Austern Date: 1998-11-20
+View all other issues in [istream.formatted.arithmetic].
+View all issues with WP status.
+Discussion:
+Formatted input is defined for the types short, unsigned short, int, +unsigned int, long, unsigned long, float, double, +long double, bool, and void*. According to section 27.6.1.2.2, +formatted input of a value x is done as if by the following code fragment:
+ +typedef num_get< charT,istreambuf_iterator<charT,traits> > numget; +iostate err = 0; +use_facet< numget >(loc).get(*this, 0, *this, err, val); +setstate(err);+ +
According to section 22.2.2.1.1 [facet.num.get.members], however, +num_get<>::get() is only overloaded for the types +bool, long, unsigned short, unsigned +int, unsigned long, unsigned long, +float, double, long double, and +void*. Comparing the lists from the two sections, we find +that 27.6.1.2.2 is using a nonexistent function for types +short and int.
+ + +Proposed resolution:
+In 27.6.1.2.2 [istream.formatted.arithmetic] Arithmetic Extractors, remove the +two lines (1st and 3rd) which read:
+++ +operator>>(short& val); +... +operator>>(int& val);+
And add the following at the end of that section (27.6.1.2.2) :
+ +++ +operator>>(short& val);+The conversion occurs as if performed by the following code fragment (using + the same notation as for the preceding code fragment):
+typedef num_get< charT,istreambuf_iterator<charT,traits> > numget; + iostate err = 0; + long lval; + use_facet< numget >(loc).get(*this, 0, *this, err, lval); + if (err == 0 + && (lval < numeric_limits<short>::min() || numeric_limits<short>::max() < lval)) + err = ios_base::failbit; + setstate(err);+operator>>(int& val);+The conversion occurs as if performed by the following code fragment (using + the same notation as for the preceding code fragment):
+typedef num_get< charT,istreambuf_iterator<charT,traits> > numget; + iostate err = 0; + long lval; + use_facet< numget >(loc).get(*this, 0, *this, err, lval); + if (err == 0 + && (lval < numeric_limits<int>::min() || numeric_limits<int>::max() < lval)) + err = ios_base::failbit; + setstate(err);+
[Post-Tokyo: PJP provided the above wording.]
+ + + + + + +Section: 17.4.4.9 [res.on.exception.handling] Status: TC + Submitter: Judy Ward Date: 1998-12-15
+View all other issues in [res.on.exception.handling].
+View all issues with TC status.
+Discussion:
+Section 17.4.4.9 [res.on.exception.handling] states:
+ +"An implementation may strengthen the exception-specification +for a function by removing listed exceptions."
+ +The problem is that if an implementation is allowed to do this for +virtual functions, then a library user cannot write a class that +portably derives from that class.
+ +For example, this would not compile if ios_base::failure::~failure +had an empty exception specification:
+ +#include <ios> +#include <string> + +class D : public std::ios_base::failure { +public: + D(const std::string&); + ~D(); // error - exception specification must be compatible with + // overridden virtual function ios_base::failure::~failure() +};+ + +
Proposed resolution:
+Change Section 17.4.4.9 [res.on.exception.handling] from:
+ +"may strengthen the +exception-specification for a function"
+ +to:
+ +"may strengthen the +exception-specification for a non-virtual function".
+ + + + + +Section: 17.4.3.2 [reserved.names] Status: WP + Submitter: Judy Ward Date: 1998-12-15
+View all other issues in [reserved.names].
+View all issues with WP status.
+Discussion:
+ +The original issue asked whether a library implementor could +specialize standard library templates for built-in types. (This was +an issue because users are permitted to explicitly instantiate +standard library templates.)
+ +Specializations are no longer a problem, because of the resolution +to core issue 259. Under the proposed resolution, it will be legal +for a translation unit to contain both a specialization and an +explicit instantiation of the same template, provided that the +specialization comes first. In such a case, the explicit +instantiation will be ignored. Further discussion of library issue +120 assumes that the core 259 resolution will be adopted.
+ +However, as noted in lib-7047, one piece of this issue still +remains: what happens if a standard library implementor explicitly +instantiates a standard library templates? It's illegal for a program +to contain two different explicit instantiations of the same template +for the same type in two different translation units (ODR violation), +and the core working group doesn't believe it is practical to relax +that restriction.
+ +The issue, then, is: are users allowed to explicitly instantiate +standard library templates for non-user defined types? The status quo +answer is 'yes'. Changing it to 'no' would give library implementors +more freedom.
+ +This is an issue because, for performance reasons, library +implementors often need to explicitly instantiate standard library +templates. (for example, std::basic_string<char>) Does giving +users freedom to explicitly instantiate standard library templates for +non-user defined types make it impossible or painfully difficult for +library implementors to do this?
+ +John Spicer suggests, in lib-8957, that library implementors have a +mechanism they can use for explicit instantiations that doesn't +prevent users from performing their own explicit instantiations: put +each explicit instantiation in its own object file. (Different +solutions might be necessary for Unix DSOs or MS-Windows DLLs.) On +some platforms, library implementors might not need to do anything +special: the "undefined behavior" that results from having two +different explicit instantiations might be harmless.
+ + + +Proposed resolution:
+Append to 17.4.3.2 [reserved.names] paragraph 1:
++ ++ A program may explicitly instantiate any templates in the standard + library only if the declaration depends on the name of a user-defined + type of external linkage and the instantiation meets the standard library + requirements for the original template. +
[Kona: changed the wording from "a user-defined name" to "the name of + a user-defined type"]
+ + + + +Rationale:
+The LWG considered another possible resolution:
+++ +In light of the resolution to core issue 259, no normative changes + in the library clauses are necessary. Add the following non-normative + note to the end of 17.4.3.2 [reserved.names] paragraph 1:
+++ [Note: A program may explicitly instantiate standard library + templates, even when an explicit instantiation does not depend on + a user-defined name. --end note] +
The LWG rejected this because it was believed that it would make + it unnecessarily difficult for library implementors to write + high-quality implementations. A program may not include an + explicit instantiation of the same template, for the same template + arguments, in two different translation units. If users are + allowed to provide explicit instantiations of Standard Library + templates for built-in types, then library implementors aren't, + at least not without nonportable tricks.
+ +The most serious problem is a class template that has writeable + static member variables. Unfortunately, such class templates are + important and, in existing Standard Library implementations, are + often explicitly specialized by library implementors: locale facets, + which have a writeable static member variable id. If a + user's explicit instantiation collided with the implementations + explicit instantiation, iostream initialization could cause locales + to be constructed in an inconsistent state.
+ +One proposed implementation technique was for Standard Library + implementors to provide explicit instantiations in separate object + files, so that they would not be picked up by the linker when the + user also provides an explicit instantiation. However, this + technique only applies for Standard Library implementations that + are packaged as static archives. Most Standard Library + implementations nowadays are packaged as dynamic libraries, so this + technique would not apply.
+ +The Committee is now considering standardization of dynamic + linking. If there are such changes in the future, it may be + appropriate to revisit this issue later.
+ + + + + +Section: 27.5.2 [streambuf] Status: TC + Submitter: Judy Ward Date: 1998-12-15
+View all other issues in [streambuf].
+View all issues with TC status.
+Discussion:
+Section 27.5.2 describes the streambuf classes this way:
+ ++ ++ +The class streambuf is a specialization of the template class basic_streambuf +specialized for the type char.
+ +The class wstreambuf is a specialization of the template class basic_streambuf +specialized for the type wchar_t.
+ +
This implies that these classes must be template specializations, not typedefs.
+ +It doesn't seem this was intended, since Section 27.5 has them declared as typedefs.
+ + +Proposed resolution:
+Remove 27.5.2 [streambuf] paragraphs 2 and 3 (the above two +sentences).
+ + +Rationale:
+The streambuf synopsis already has a declaration for the +typedefs and that is sufficient.
+ + + + + +Section: 26.5.5.3 [slice.arr.fill], 26.5.7.3 [gslice.array.fill], 26.5.8.3 [mask.array.fill], 26.5.9.3 [indirect.array.fill] Status: WP + Submitter: Judy Ward Date: 1998-12-15
+View all issues with WP status.
+Discussion:
+One of the operator= in the valarray helper arrays is const and one +is not. For example, look at slice_array. This operator= in Section +26.5.5.1 [slice.arr.assign] is const:
+ +void operator=(const valarray<T>&) const;
+ +but this one in Section 26.5.5.3 [slice.arr.fill] is not:
+ +void operator=(const T&);
+ +The description of the semantics for these two functions is similar.
+ + +Proposed resolution:
+ +26.5.5 [template.slice.array] Template class slice_array
++ ++ +In the class template definition for slice_array, replace the member + function declaration
+void operator=(const T&); ++with
+void operator=(const T&) const; ++
26.5.5.3 [slice.arr.fill] slice_array fill function
++ ++ +Change the function declaration
+void operator=(const T&); ++to
+void operator=(const T&) const; ++
26.5.7 [template.gslice.array] Template class gslice_array
++ ++ +In the class template definition for gslice_array, replace the member + function declaration
+void operator=(const T&); ++with
+void operator=(const T&) const; ++
26.5.7.3 [gslice.array.fill] gslice_array fill function
++ ++ +Change the function declaration
+void operator=(const T&); ++to
+void operator=(const T&) const; ++
26.5.8 [template.mask.array] Template class mask_array
++ ++ +In the class template definition for mask_array, replace the member + function declaration
+void operator=(const T&); ++with
+void operator=(const T&) const; ++
26.5.8.3 [mask.array.fill] mask_array fill function
++ ++ +Change the function declaration
+void operator=(const T&); ++to
+void operator=(const T&) const; ++
26.5.9 [template.indirect.array] Template class indirect_array
++ ++ +In the class template definition for indirect_array, replace the member + function declaration
+void operator=(const T&); ++with
+void operator=(const T&) const; ++
26.5.9.3 [indirect.array.fill] indirect_array fill function
++ ++ + +Change the function declaration
+void operator=(const T&); ++to
+void operator=(const T&) const; ++
[Redmond: Robert provided wording.]
+ + + + +Rationale:
+There's no good reason for one version of operator= being const and +another one not. Because of issue 253, this now +matters: these functions are now callable in more circumstances. In +many existing implementations, both versions are already const.
+ + + + + +Section: 22.2.1.2 [locale.ctype.byname] Status: TC + Submitter: Judy Ward Date: 1998-12-15
+View all other issues in [locale.ctype.byname].
+View all issues with TC status.
+Discussion:
+In Section 22.2.1.2 [locale.ctype.byname] +ctype_byname<charT>::do_scan_is() and do_scan_not() are declared +to return a const char* not a const charT*.
+ + +Proposed resolution:
+Change Section 22.2.1.2 [locale.ctype.byname] do_scan_is() and +do_scan_not() to return a const +charT*.
+ + + + + +Section: 26.5.2 [template.valarray] Status: TC + Submitter: Judy Ward Date: 1998-12-15
+View all other issues in [template.valarray].
+View all issues with TC status.
+Discussion:
+In Section 26.5.2 [template.valarray] valarray<T>::operator!() +is +declared to return a valarray<T>, but in Section 26.5.2.5 +[valarray.unary] it is declared to return a valarray<bool>. The +latter appears to be correct.
+ + +Proposed resolution:
+Change in Section 26.5.2 [template.valarray] the declaration of +operator!() so that the return type is +valarray<bool>.
+ + + + +Section: 22.2.1.1.2 [locale.ctype.virtuals] Status: TC + Submitter: Judy Ward Date: 1998-12-15
+View all other issues in [locale.ctype.virtuals].
+View all issues with TC status.
+Discussion:
Typos in 22.2.1.1.2 need to be fixed.
+ +Proposed resolution:
+In Section 22.2.1.1.2 [locale.ctype.virtuals] change:
+ +do_widen(do_narrow(c),0) == c+ +
to:
+ +do_widen(do_narrow(c,0)) == c+ +
and change:
+ +(is(M,c) || !ctc.is(M, do_narrow(c),dfault) )+ +
to:
+ +(is(M,c) || !ctc.is(M, do_narrow(c,dfault)) )+ + + + + +
Section: D.9.1 [auto.ptr] Status: TC + Submitter: Greg Colvin Date: 1999-02-17
+View all other issues in [auto.ptr].
+View all issues with TC status.
+Discussion:
+There are two problems with the current auto_ptr wording +in the standard:
+ +First, the auto_ptr_ref definition cannot be nested +because auto_ptr<Derived>::auto_ptr_ref is unrelated to +auto_ptr<Base>::auto_ptr_ref. Also submitted by +Nathan Myers, with the same proposed resolution.
+ +Second, there is no auto_ptr assignment operator taking an +auto_ptr_ref argument.
+ +I have discussed these problems with my proposal coauthor, Bill +Gibbons, and with some compiler and library implementors, and we +believe that these problems are not desired or desirable implications +of the standard.
+ +25 Aug 1999: The proposed resolution now reflects changes suggested +by Dave Abrahams, with Greg Colvin's concurrence; 1) changed +"assignment operator" to "public assignment +operator", 2) changed effects to specify use of release(), 3) +made the conversion to auto_ptr_ref const.
+ +2 Feb 2000: Lisa Lippincott comments: [The resolution of] this issue +states that the conversion from auto_ptr to auto_ptr_ref should +be const. This is not acceptable, because it would allow +initialization and assignment from _any_ const auto_ptr! It also +introduces an implementation difficulty in writing this conversion +function -- namely, somewhere along the line, a const_cast will be +necessary to remove that const so that release() may be called. This +may result in undefined behavior [7.1.5.1/4]. The conversion +operator does not have to be const, because a non-const implicit +object parameter may be bound to an rvalue [13.3.3.1.4/3] +[13.3.1/5].
+ +Tokyo: The LWG removed the following from the proposed resolution:
+ +In 20.5.4 [meta.unary], paragraph 2, and 20.5.4.3 [meta.unary.prop], + paragraph 2, make the conversion to auto_ptr_ref const:
+++ + +template<class Y> operator auto_ptr_ref<Y>() const throw();+
Proposed resolution:
+In 20.5.4 [meta.unary], paragraph 2, move +the auto_ptr_ref definition to namespace scope.
+ +In 20.5.4 [meta.unary], paragraph 2, add +a public assignment operator to the auto_ptr definition:
+ +++ +auto_ptr& operator=(auto_ptr_ref<X> r) throw();+
Also add the assignment operator to 20.5.4.3 [meta.unary.prop]:
+ +++ + + + + +auto_ptr& operator=(auto_ptr_ref<X> r) throw()+ +Effects: Calls reset(p.release()) for the auto_ptr + p that r holds a reference to.
+ +
+ Returns: *this.
Section: 27.6.1.3 [istream.unformatted], 27.6.2.5 [ostream.seeks] Status: TC + Submitter: Angelika Langer Date: 1999-02-22
+View all other issues in [istream.unformatted].
+View all issues with TC status.
+Discussion:
+Currently, the standard does not specify how seekg() and seekp() +indicate failure. They are not required to set failbit, and they can't +return an error indication because they must return *this, i.e. the +stream. Hence, it is undefined what happens if they fail. And they +can fail, for instance, when a file stream is disconnected from the +underlying file (is_open()==false) or when a wide character file +stream must perform a state-dependent code conversion, etc.
+ +The stream functions seekg() and seekp() should set failbit in the +stream state in case of failure.
+ + +Proposed resolution:
+Add to the Effects: clause of seekg() in +27.6.1.3 [istream.unformatted] and to the Effects: clause of seekp() in +27.6.2.5 [ostream.seeks]:
+ +++ + +In case of failure, the function calls setstate(failbit) (which may throw ios_base::failure). +
+
Rationale:
+Setting failbit is the usual error reporting mechanism for streams
+ + + + +Section: 23.1.4 [associative.reqmts], 23.1.3 [sequence.reqmts] Status: DR + Submitter: Andrew Koenig Date: 1999-03-02
+View all other issues in [associative.reqmts].
+View all issues with DR status.
+Duplicate of: 451
+Discussion:
+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.4 [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.4 [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 [map], in the map class synopsis; and +in 23.3.2 [multimap], in the multimap class synopsis; and +in 23.3.3 [set], in the set class synopsis; and +in 23.3.4 [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, +(reflected above) which we will review at the next meeting. +]
+ + +[ +Redmond: formally voted into WP. +]
+ + + + + + + +Section: 23.2.4.2 [list.capacity] Status: TC + Submitter: Howard Hinnant Date: 1999-03-06
+View all issues with TC status.
+Discussion:
+The description reads:
+ +-1- Effects:
+ +if (sz > size()) + insert(end(), sz-size(), c); + else if (sz < size()) + erase(begin()+sz, end()); + else + ; // do nothing+ +
Obviously list::resize should not be specified in terms of random access iterators.
+ + +Proposed resolution:
+Change 23.2.4.2 [list.capacity] paragraph 1 to:
+ +Effects:
+ +if (sz > size()) + insert(end(), sz-size(), c); + else if (sz < size()) + { + iterator i = begin(); + advance(i, sz); + erase(i, end()); + }+ +
[Dublin: The LWG asked Howard to discuss exception safety offline +with David Abrahams. They had a discussion and believe there is +no issue of exception safety with the proposed resolution.]
+ + + + + + +Section: 23.3.1 [map] Status: TC + Submitter: Howard Hinnant Date: 1999-03-06
+View all other issues in [map].
+View all issues with TC status.
+Discussion:
The title says it all.
+ +Proposed resolution:
+Insert in 23.3.1 [map], paragraph 2, +after operator= in the map declaration:
+ +allocator_type get_allocator() const;+ + + + +
Section: 23.2.6.1 [vector.cons] Status: TC + Submitter: Howard Hinnant Date: 1999-03-06
+View all issues with TC status.
+Discussion:
+The complexity description says: "It does at most 2N calls to the copy constructor +of T and logN reallocations if they are just input iterators ...".
+ +This appears to be overly restrictive, dictating the precise memory/performance +tradeoff for the implementor.
+ + +Proposed resolution:
+Change 23.2.6.1 [vector.cons], paragraph 1 to:
+ +-1- Complexity: The constructor template <class +InputIterator> vector(InputIterator first, InputIterator last) +makes only N calls to the copy constructor of T (where N is the +distance between first and last) and no reallocations if iterators +first and last are of forward, bidirectional, or random access +categories. It makes order N calls to the copy constructor of T and +order logN reallocations if they are just input iterators. +
+ + +Rationale:
+"at most 2N calls" is correct only if the growth factor +is greater than or equal to 2. +
+ + + + +Section: 27.6.1.3 [istream.unformatted] Status: WP + Submitter: Howard Hinnant Date: 1999-03-06
+View all other issues in [istream.unformatted].
+View all issues with WP status.
+Discussion:
+I may be misunderstanding the intent, but should not seekg set only +the input stream and seekp set only the output stream? The description +seems to say that each should set both input and output streams. If +that's really the intent, I withdraw this proposal.
+ + +Proposed resolution:
+In section 27.6.1.3 change:
+ +basic_istream<charT,traits>& seekg(pos_type pos); +Effects: If fail() != true, executes rdbuf()->pubseekpos(pos).+ +
To:
+ +basic_istream<charT,traits>& seekg(pos_type pos); +Effects: If fail() != true, executes rdbuf()->pubseekpos(pos, ios_base::in).+ +
In section 27.6.1.3 change:
+ +basic_istream<charT,traits>& seekg(off_type& off, ios_base::seekdir dir); +Effects: If fail() != true, executes rdbuf()->pubseekoff(off, dir).+ +
To:
+ +basic_istream<charT,traits>& seekg(off_type& off, ios_base::seekdir dir); +Effects: If fail() != true, executes rdbuf()->pubseekoff(off, dir, ios_base::in).+ +
In section 27.6.2.4, paragraph 2 change:
+ +-2- Effects: If fail() != true, executes rdbuf()->pubseekpos(pos).+ +
To:
+ +-2- Effects: If fail() != true, executes rdbuf()->pubseekpos(pos, ios_base::out).+ +
In section 27.6.2.4, paragraph 4 change:
+ +-4- Effects: If fail() != true, executes rdbuf()->pubseekoff(off, dir).+ +
To:
+ +-4- Effects: If fail() != true, executes rdbuf()->pubseekoff(off, dir, ios_base::out).+ +
[Dublin: Dietmar Kühl thinks this is probably correct, but would +like the opinion of more iostream experts before taking action.]
+ + +[Tokyo: Reviewed by the LWG. PJP noted that although his docs are +incorrect, his implementation already implements the Proposed +Resolution.]
+ + +[Post-Tokyo: Matt Austern comments:
+Is it a problem with basic_istream and basic_ostream, or is it a problem
+with basic_stringbuf?
+We could resolve the issue either by changing basic_istream and
+basic_ostream, or by changing basic_stringbuf. I prefer the latter
+change (or maybe both changes): I don't see any reason for the standard to
+require that std::stringbuf s(std::string("foo"), std::ios_base::in);
+s.pubseekoff(0, std::ios_base::beg); must fail.
+This requirement is a bit weird. There's no similar requirement
+for basic_streambuf<>::seekpos, or for basic_filebuf<>::seekoff or
+basic_filebuf<>::seekpos.]
Section: 22.1.1 [locale] Status: TC + Submitter: Angelika Langer Date: 1999-03-17
+View all other issues in [locale].
+View all issues with TC status.
+Discussion:
+Section 22.1.1 [locale] says:
+ +-4- In the call to use_facet<Facet>(loc), the type argument +chooses a facet, making available all members of the named type. If +Facet is not present in a locale (or, failing that, in the global +locale), it throws the standard exception bad_cast. A C++ program can +check if a locale implements a particular facet with the template +function has_facet<Facet>().
+ +This contradicts the specification given in section
+22.1.2 [locale.global.templates]:
+
+template <class Facet> const Facet& use_facet(const
+locale& loc);
+
+-1- Get a reference to a facet of a locale.
+-2- Returns: a reference to the corresponding facet of loc, if present.
+-3- Throws: bad_cast if has_facet<Facet>(loc) is false.
+-4- Notes: The reference returned remains valid at least as long as any copy of loc exists
+
Proposed resolution:
+Remove the phrase "(or, failing that, in the global locale)" +from section 22.1.1.
+ + +Rationale:
+Needed for consistency with the way locales are handled elsewhere +in the standard.
+ + + + +Section: 23.1.3 [sequence.reqmts] Status: TC + Submitter: Andrew Koenig Date: 1999-03-30
+View all other issues in [sequence.reqmts].
+View all issues with TC status.
+Discussion:
+The sentence introducing the Optional sequence operation table +(23.1.1 paragraph 12) has two problems:
+ +A. It says ``The operations in table 68 are provided only for the containers for which
+they take constant time.''
+
+That could be interpreted in two ways, one of them being ``Even though table 68 shows
+particular operations as being provided, implementations are free to omit them if they
+cannot implement them in constant time.''
+
+B. That paragraph says nothing about amortized constant time, and it should.
Proposed resolution:
+Replace the wording in 23.1.1 paragraph 12 which begins ``The operations in table 68 are provided only..." +with:
+ +++ + + + +Table 68 lists sequence operations that are provided for some types of sequential + containers but not others. An implementation shall provide these operations for all + container types shown in the ``container'' column, and shall implement them so as to take + amortized constant time.
+
Section: 21.3.6.4 [string::insert], 21.3.6.6 [string::replace] Status: TC + Submitter: Arch Robison Date: 1999-04-28
+View all other issues in [string::insert].
+View all issues with TC status.
+Discussion:
+Sections 21.3.6.4 paragraph 1 and 21.3.6.6 paragraph 1 surely have misprints where they
+say:
+
+— xpos <= pos and pos < size();
Surely the document meant to say ``xpos < size()'' in both places.
+ +[Judy Ward also sent in this issue for 21.3.6.4 with the same +proposed resolution.]
+ + + +Proposed resolution:
+Change Sections 21.3.6.4 paragraph 1 and 21.3.6.6 paragraph 1, the line which says:
+
+— xpos <= pos and pos < size();
+
+to:
+
+— xpos <= pos and xpos < size();
Section: 25.3.8 [alg.lex.comparison] Status: TC + Submitter: Howard Hinnant Date: 1999-06-20
+View all issues with TC status.
+Discussion:
+The lexicographical_compare complexity is specified as:
+
+ "At most min((last1 - first1), (last2 - first2))
+applications of the corresponding comparison."
+
+The best I can do is twice that expensive.
Nicolai Josuttis comments in lib-6862: You mean, to check for +equality you have to check both < and >? Yes, IMO you are +right! (and Matt states this complexity in his book)
+ + + +Proposed resolution:
+Change 25.3.8 [alg.lex.comparison] complexity to:
++ ++ At most 2*min((last1 - first1), (last2 - first2)) + applications of the corresponding comparison. +
Change the example at the end of paragraph 3 to read:
++ + + + ++ [Example:
+
+ for ( ; first1 != last1 && first2 != last2 ; + ++first1, ++first2) {
+ if (*first1 < *first2) return true;
+ if (*first2 < *first1) return false;
+ }
+ return first1 == last1 && first2 != last2;
+
+ --end example] +
Section: 23.2.2.1 [deque.cons] Status: TC + Submitter: Herb Sutter Date: 1999-05-09
+View all other issues in [deque.cons].
+View all issues with TC status.
+Discussion:
+In 23.2.2.1 [deque.cons] paragraph 6, the deque ctor that takes an iterator range appears +to have complexity requirements which are incorrect, and which contradict the +complexity requirements for insert(). I suspect that the text in question, +below, was taken from vector:
+++Complexity: If the iterators first and last are forward iterators, + bidirectional iterators, or random access iterators the constructor makes only + N calls to the copy constructor, and performs no reallocations, where N is + last - first.
+
The word "reallocations" does not really apply to deque. Further, +all of the following appears to be spurious:
+++It makes at most 2N calls to the copy constructor of T and log N + reallocations if they are input iterators.1)
+1) The complexity is greater in the case of input iterators because each + element must be added individually: it is impossible to determine the distance + between first abd last before doing the copying.
+
This makes perfect sense for vector, but not for deque. Why should deque gain +an efficiency advantage from knowing in advance the number of elements to +insert?
+ + +Proposed resolution:
+In 23.2.2.1 [deque.cons] paragraph 6, replace the Complexity description, including the +footnote, with the following text (which also corrects the "abd" +typo):
+++ + + + +Complexity: Makes last - first calls to the copy constructor of T.
+
Section: 26.3.6 [complex.ops] Status: TC + Submitter: Angelika Langer Date: 1999-05-12
+View all other issues in [complex.ops].
+View all issues with TC status.
+Discussion:
+The extractor for complex numbers is specified as:
+ ++ ++template<class T, class charT, class traits>
+ +
+ basic_istream<charT, traits>&
+ operator>>(basic_istream<charT, traits>& is, complex<T>& x);
+
+Effects: Extracts a complex number x of the form: u, (u), or (u,v), +where u is the real part and v is the imaginary part +(lib.istream.formatted).
+Requires: The input values be convertible to T. If bad input is +encountered, calls is.setstate(ios::failbit) (which may throw +ios::failure (lib.iostate.flags).
+Returns: is .
Is it intended that the extractor for complex numbers does not skip
+whitespace, unlike all other extractors in the standard library do?
+Shouldn't a sentry be used?
+
+The inserter for complex numbers is specified as:
+ ++ +template<class T, class charT, class traits>
+ +
+ basic_ostream<charT, traits>&
+ operator<<(basic_ostream<charT, traits>& o, const complex<T>& x);
+
+Effects: inserts the complex number x onto the stream o as if it were implemented as follows:
+
+ template<class T, class charT, class traits>
+ basic_ostream<charT, traits>&
+ operator<<(basic_ostream<charT, traits>& o, const complex<T>& x)
+ {
+ basic_ostringstream<charT, traits> s;
+ s.flags(o.flags());
+ s.imbue(o.getloc());
+ s.precision(o.precision());
+ s << '(' << x.real() << "," << x.imag() << ')';
+ return o << s.str();
+ }
Is it intended that the inserter for complex numbers ignores the +field width and does not do any padding? If, with the suggested +implementation above, the field width were set in the stream then the +opening parentheses would be adjusted, but the rest not, because the +field width is reset to zero after each insertion.
+ +I think that both operations should use sentries, for sake of +consistency with the other inserters and extractors in the +library. Regarding the issue of padding in the inserter, I don't know +what the intent was.
+ + +Proposed resolution:
+After 26.3.6 [complex.ops] paragraph 14 (operator>>), add a +Notes clause:
+ ++ ++ + +Notes: This extraction is performed as a series of simpler +extractions. Therefore, the skipping of whitespace is specified to be the +same for each of the simpler extractions.
+ +
Rationale:
+For extractors, the note is added to make it clear that skipping whitespace +follows an "all-or-none" rule.
+ +For inserters, the LWG believes there is no defect; the standard is correct +as written.
+ + + + +Section: 17.4.4.3 [global.functions] Status: TC + Submitter: Lois Goldthwaite Date: 1999-06-04
+View all other issues in [global.functions].
+View all issues with TC status.
+Discussion:
+The library had many global functions until 17.4.1.1 [lib.contents] +paragraph 2 was added:
+ ++ ++ +All library entities except macros, operator new and operator +delete are defined within the namespace std or namespaces nested +within namespace std.
+ +
It appears "global function" was never updated in the following:
+ ++ ++ + +17.4.4.3 - Global functions [lib.global.functions]
+ +
+
+-1- It is unspecified whether any global functions in the C++ Standard +Library are defined as inline (dcl.fct.spec).
+
+-2- A call to a global function signature described in Clauses +lib.language.support through lib.input.output behaves the same as if +the implementation declares no additional global function +signatures.*
+
+ [Footnote: A valid C++ program always calls the expected library + global function. An implementation may also define additional + global functions that would otherwise not be called by a valid C++ + program. --- end footnote]
+
+-3- A global function cannot be declared by the implementation as +taking additional default arguments.
+
+17.4.4.4 - Member functions [lib.member.functions]
+
+-2- An implementation can declare additional non-virtual member +function signatures within a class:+ ++-- by adding arguments with default values to a member function +signature; The same latitude does not extend to the implementation of +virtual or global functions, however.
+ +
Proposed resolution:
+Change "global" to "global or non-member" in:
+++ + +17.4.4.3 [lib.global.functions] section title,
+
+ 17.4.4.3 [lib.global.functions] para 1,
+ 17.4.4.3 [lib.global.functions] para 2 in 2 places plus 2 + places in the footnote,
+ 17.4.4.3 [lib.global.functions] para 3,
+ 17.4.4.4 [lib.member.functions] para 2
Rationale:
++Because operator new and delete are global, the proposed resolution +was changed from "non-member" to "global or non-member. +
+ + + + +Section: 22.2.8 [facets.examples] Status: TC + Submitter: Jeremy Siek Date: 1999-06-03
+View all other issues in [facets.examples].
+View all issues with TC status.
+Discussion:
+In 22.2.8 [facets.examples] paragraph 13, the do_truename() and +do_falsename() functions in the example facet BoolNames should be +const. The functions they are overriding in +numpunct_byname<char> are const.
+ + +Proposed resolution:
+In 22.2.8 [facets.examples] paragraph 13, insert "const" in +two places:
+++ + + + +string do_truename() const { return "Oui Oui!"; }
+
+ string do_falsename() const { return "Mais Non!"; }
Section: 25.1.7 [alg.find.first.of] Status: TC + Submitter: Matt McClure Date: 1999-06-30
+View all other issues in [alg.find.first.of].
+View all issues with TC status.
+Discussion:
+ + +Proposed resolution:
+Change 25.1.7 [alg.find.first.of] paragraph 2 from:
+ +++ +Returns: The first iterator i in the range [first1, last1) such +that for some integer j in the range [first2, last2) ...
+
to:
+ +++ + + + +Returns: The first iterator i in the range [first1, last1) such +that for some iterator j in the range [first2, last2) ...
+
Section: 23.1.3 [sequence.reqmts] Status: TC + Submitter: Ed Brey Date: 1999-06-21
+View all other issues in [sequence.reqmts].
+View all issues with TC status.
+Discussion:
+For both sequences and associative containers, a.clear() has the
+semantics of erase(a.begin(),a.end()), which is undefined for an empty
+container since erase(q1,q2) requires that q1 be dereferenceable
+(23.1.1,3 and 23.1.2,7). When the container is empty, a.begin() is
+not dereferenceable.
+
+The requirement that q1 be unconditionally dereferenceable causes many
+operations to be intuitively undefined, of which clearing an empty
+container is probably the most dire.
+
+Since q1 and q2 are only referenced in the range [q1, q2), and [q1,
+q2) is required to be a valid range, stating that q1 and q2 must be
+iterators or certain kinds of iterators is unnecessary.
+
Proposed resolution:
+In 23.1.1, paragraph 3, change:
+++p and q2 denote valid iterators to a, q and q1 denote valid dereferenceable iterators to a, [q1, q2) denotes a valid range
+
to:
+++p denotes a valid iterator to a, q denotes a valid dereferenceable iterator to a, [q1, q2) denotes a valid range + in a
+
In 23.1.2, paragraph 7, change:
+++p and q2 are valid iterators to a, q and q1 are valid dereferenceable + iterators to a, [q1, q2) is a valid range
+
to
+++ + + + +p is a valid iterator to a, q is a valid dereferenceable iterator to a, [q1, q2) is a valid range + into a
+
Section: 22.2.1.1.2 [locale.ctype.virtuals] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [locale.ctype.virtuals].
+View all issues with TC status.
+Discussion:
+The semantics of scan_is() (paragraphs 4 and 6) is not exactly described +because there is no function is() which only takes a character as +argument. Also, in the effects clause (paragraph 3), the semantic is also kept +vague.
+ + +Proposed resolution:
+In 22.2.1.1.2 [locale.ctype.virtuals] paragraphs 4 and 6, change the returns +clause from:
+++"... such that is(*p) +would..."
+
to: "... such that is(m, *p) + would...."
+ + + + + +Section: 22.2.1.3.2 [facet.ctype.char.members] Status: WP + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [facet.ctype.char.members].
+View all issues with WP status.
+Duplicate of: 207
+Discussion:
+The description of the array version of narrow() (in +paragraph 11) is flawed: There is no member do_narrow() which +takes only three arguments because in addition to the range a default +character is needed.
+ +Additionally, for both widen and narrow we have +two signatures followed by a Returns clause that only addresses +one of them.
+ + + +Proposed resolution:
+Change the returns clause in 22.2.1.3.2 [facet.ctype.char.members] +paragraph 10 from:
+Returns: do_widen(low, high, to).
+ +to:
+Returns: do_widen(c) or do_widen(low, high, to), +respectively.
+ +Change 22.2.1.3.2 [facet.ctype.char.members] paragraph 10 and 11 from:
+char narrow(char c, char /*dfault*/) const; + const char* narrow(const char* low, const char* high, + char /*dfault*/, char* to) const;+
Returns: do_narrow(low, high, to).+
to:
+char narrow(char c, char dfault) const; + const char* narrow(const char* low, const char* high, + char dfault, char* to) const;+
Returns: do_narrow(c, dfault) or + do_narrow(low, high, dfault, to), respectively.+ +
[Kona: 1) the problem occurs in additional places, 2) a user +defined version could be different.]
+ + +[Post-Tokyo: Dietmar provided the above wording at the request of +the LWG. He could find no other places the problem occurred. He +asks for clarification of the Kona "a user defined +version..." comment above. Perhaps it was a circuitous way of +saying "dfault" needed to be uncommented?]
+ + +[Post-Toronto: the issues list maintainer has merged in the +proposed resolution from issue 207, which addresses the +same paragraphs.]
+ + + + + + +Section: 22.2.2.1.2 [facet.num.get.virtuals] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View other active issues in [facet.num.get.virtuals].
+View all other issues in [facet.num.get.virtuals].
+View all issues with TC status.
+Discussion:
+The table in paragraph 7 for the length modifier does not list the length +modifier l to be applied if the type is double. Thus, the +standard asks the implementation to do undefined things when using scanf() +(the missing length modifier for scanf() when scanning doubles +is actually a problem I found quite often in production code, too).
+ + +Proposed resolution:
+In 22.2.2.1.2 [facet.num.get.virtuals], paragraph 7, add a row in the Length +Modifier table to say that for double a length modifier +l is to be used.
+ + +Rationale:
+The standard makes an embarrassing beginner's mistake.
+ + + + +Section: 27.3 [iostream.objects] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [iostream.objects].
+View all issues with TC status.
+Discussion:
+There are conflicting statements about where the class +Init is defined. According to 27.3 [iostream.objects] paragraph 2 +it is defined as basic_ios::Init, according to 27.4.2 [ios.base] it is defined as ios_base::Init.
+ + +Proposed resolution:
+Change 27.3 [iostream.objects] paragraph 2 from +"basic_ios::Init" to +"ios_base::Init".
+ + +Rationale:
+Although not strictly wrong, the standard was misleading enough to warrant +the change.
+ + + + +Section: 27.4.2.3 [ios.base.locales] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [ios.base.locales].
+View all issues with TC status.
+Discussion:
+There is a small discrepancy between the declarations of +imbue(): in 27.4.2 [ios.base] the argument is passed as +locale const& (correct), in 27.4.2.3 [ios.base.locales] it +is passed as locale const (wrong).
+ + +Proposed resolution:
+In 27.4.2.3 [ios.base.locales] change the imbue argument +from "locale const" to "locale +const&".
+ + + + +Section: 27.5.2.4.2 [streambuf.virt.buffer] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [streambuf.virt.buffer].
+View all issues with TC status.
+Discussion:
+The default behavior of setbuf() is described only for the +situation that gptr() != 0 && gptr() != egptr(): +namely to do nothing. What has to be done in other situations +is not described although there is actually only one reasonable +approach, namely to do nothing, too.
+ +Since changing the buffer would almost certainly mess up most +buffer management of derived classes unless these classes do it +themselves, the default behavior of setbuf() should always be +to do nothing.
+ + +Proposed resolution:
+Change 27.5.2.4.2 [streambuf.virt.buffer], paragraph 3, Default behavior, +to: "Default behavior: Does nothing. Returns this."
+ + + + +Section: 27.5.2.4.3 [streambuf.virt.get] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all issues with TC status.
+Discussion:
+The description of the meaning of the result of +showmanyc() seems to be rather strange: It uses calls to +underflow(). Using underflow() is strange because +this function only reads the current character but does not extract +it, uflow() would extract the current character. This should +be fixed to use sbumpc() instead.
+ + +Proposed resolution:
+Change 27.5.2.4.3 [streambuf.virt.get] paragraph 1, +showmanyc()returns clause, by replacing the word +"supplied" with the words "extracted from the +stream".
+ + + + +Section: 27.6.1.1 [istream] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [istream].
+View all issues with TC status.
+Discussion:
+The paragraph 4 refers to the function exception() which +is not defined. Probably, the referred function is +basic_ios<>::exceptions().
+ + +Proposed resolution:
+In 27.6.1.1 [istream], 27.6.1.3 [istream.unformatted], paragraph 1, +27.6.2.1 [ostream], paragraph 3, and 27.6.2.6.1 [ostream.formatted.reqmts], +paragraph 1, change "exception()" to +"exceptions()".
+ +[Note to Editor: "exceptions" with an "s" +is the correct spelling.]
+ + + + + + +Section: 27.6.1.2.2 [istream.formatted.arithmetic] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [istream.formatted.arithmetic].
+View all issues with TC status.
+Discussion:
+The note in the second paragraph pretends that the first argument +is an object of type istream_iterator. This is wrong: It is +an object of type istreambuf_iterator.
+ + +Proposed resolution:
+Change 27.6.1.2.2 [istream.formatted.arithmetic] from:
+++The first argument provides an object of the istream_iterator class...
+
to
+++ + + + + +The first argument provides an object of the istreambuf_iterator class...
+
Section: 22.2.5.3.2 [locale.time.put.virtuals] Status: TC + Submitter: Angelika Langer Date: 1999-07-23
+View all issues with TC status.
+Discussion:
+In 22.2.5.3.2 [locale.time.put.virtuals] the do_put() function is specified
+as taking a fill character as an argument, but the description of the
+function does not say whether the character is used at all and, if so,
+in which way. The same holds for any format control parameters that
+are accessible through the ios_base& argument, such as the
+adjustment or the field width. Is strftime() supposed to use the fill
+character in any way? In any case, the specification of
+time_put.do_put() looks inconsistent to me.
Is the
+signature of do_put() wrong, or is the effects clause incomplete?
Proposed resolution:
+Add the following note after 22.2.5.3.2 [locale.time.put.virtuals] +paragraph 2:
+++ + +[Note: the fill argument may be used in the implementation-defined formats, or by derivations. A space character is a reasonable default + for this argument. --end Note]
+
Rationale:
+The LWG felt that while the normative text was correct, +users need some guidance on what to pass for the fill +argument since the standard doesn't say how it's used.
+ + + + +Section: 27.6.2.1 [ostream] Status: WP + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [ostream].
+View all issues with WP status.
+Discussion:
+Paragraph 2 explicitly states that none of the basic_ostream +functions falling into one of the groups "formatted output functions" +and "unformatted output functions" calls any stream buffer function +which might call a virtual function other than overflow(). Basically +this is fine but this implies that sputn() (this function would call +the virtual function xsputn()) is never called by any of the standard +output functions. Is this really intended? At minimum it would be convenient to +call xsputn() for strings... Also, the statement that overflow() +is the only virtual member of basic_streambuf called is in conflict +with the definition of flush() which calls rdbuf()->pubsync() +and thereby the virtual function sync() (flush() is listed +under "unformatted output functions").
+In addition, I guess that the sentence starting with "They may use other +public members of basic_ostream ..." probably was intended to +start with "They may use other public members of basic_streamuf..." +although the problem with the virtual members exists in both cases.
+I see two obvious resolutions:
+Proposed resolution:
+Change the last sentence of 27.6.2.1 (lib.ostream) paragraph 2 from:
+++They may use other public members of basic_ostream except that they do not + invoke any virtual members of rdbuf() except overflow().
+
to:
+++ +They may use other public members of basic_ostream except that they shall + not invoke any virtual members of rdbuf() except overflow(), xsputn(), and + sync().
+
[Kona: the LWG believes this is a problem. Wish to ask Jerry or +PJP why the standard is written this way.]
+ + +[Post-Tokyo: Dietmar supplied wording at the request of the +LWG. He comments: The rules can be made a little bit more specific if +necessary be explicitly spelling out what virtuals are allowed to be +called from what functions and eg to state specifically that flush() +is allowed to call sync() while other functions are not.]
+ + + + + + +Section: 27.6.2.6.4 [ostream.inserters.character] Status: WP + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [ostream.inserters.character].
+View all issues with WP status.
+Discussion:
+Paragraph 4 states that the length is determined using +traits::length(s). Unfortunately, this function is not +defined for example if the character type is wchar_t and the +type of s is char const*. Similar problems exist if +the character type is char and the type of s is +either signed char const* or unsigned char +const*.
+ + +Proposed resolution:
+Change 27.6.2.6.4 [ostream.inserters.character] paragraph 4 from:
+++Effects: Behaves like an formatted inserter (as described in + lib.ostream.formatted.reqmts) of out. After a sentry object is + constructed it inserts characters. The number of characters starting + at s to be inserted is traits::length(s). Padding is determined as + described in lib.facet.num.put.virtuals. The traits::length(s) + characters starting at s are widened using out.widen + (lib.basic.ios.members). The widened characters and any required + padding are inserted into out. Calls width(0).
+
to:
+++ +Effects: Behaves like a formatted inserter (as described in + lib.ostream.formatted.reqmts) of out. After a sentry object is + constructed it inserts n characters starting at s, + where n is the number that would be computed as if by:
++
+- traits::length(s) for the overload where the first argument is of + type basic_ostream<charT, traits>& and the second is + of type const charT*, and also for the overload where the first + argument is of type basic_ostream<char, traits>& and + the second is of type const char*.
+- std::char_traits<char>::length(s) + for the overload where the first argument is of type + basic_ostream<charT, traits>& and the second is of type + const char*.
+- traits::length(reinterpret_cast<const char*>(s)) + for the other two overloads.
+Padding is determined as described in + lib.facet.num.put.virtuals. The n characters starting at + s are widened using out.widen (lib.basic.ios.members). The + widened characters and any required padding are inserted into + out. Calls width(0).
+
[Santa Cruz: Matt supplied new wording]
+ + +[Kona: changed "where n is" to " where n is the + number that would be computed as if by"]
+ + + + +Rationale:
+We have five separate cases. In two of them we can use the +user-supplied traits class without any fuss. In the other three we +try to use something as close to that user-supplied class as possible. +In two cases we've got a traits class that's appropriate for +char and what we've got is a const signed char* or a const +unsigned char*; that's close enough so we can just use a reinterpret +cast, and continue to use the user-supplied traits class. Finally, +there's one case where we just have to give up: where we've got a +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>
+ + + + + +Section: 27.6.2.7 [ostream.unformatted] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [ostream.unformatted].
+View all issues with TC status.
+Discussion:
+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...
+ + +Proposed resolution:
+In 27.6.2.7 [ostream.unformatted] paragraph 1, the first and last +sentences, change the word "formatted" to +"unformatted":
+++ + + + +"Each unformatted output function begins ..."
+
+ "... value specified for the unformatted output + function."
Section: 27.7.1.4 [stringbuf.virtuals] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [stringbuf.virtuals].
+View all issues with TC status.
+Discussion:
+Paragraph 8, Notes, of this section seems to mandate an extremely +inefficient way of buffer handling for basic_stringbuf, +especially in view of the restriction that basic_ostream +member functions are not allowed to use xsputn() (see 27.6.2.1 [ostream]): For each character to be inserted, a new buffer +is to be created.
+Of course, the resolution below requires some handling of +simultaneous input and output since it is no longer possible to update +egptr() whenever epptr() is changed. A possible +solution is to handle this in underflow().
+ + +Proposed resolution:
+In 27.7.1.4 [stringbuf.virtuals] paragraph 8, Notes, insert the words +"at least" as in the following:
+++ + + + +To make a write position available, the function reallocates (or initially + allocates) an array object with a sufficient number of elements to hold the + current array object (if any), plus at least one additional write + position.
+
Section: 27.7.4 [stringstream] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-20
+View all issues with TC status.
+Discussion:
+The classes basic_stringstream (27.7.4 [stringstream]), +basic_istringstream (27.7.2 [istringstream]), and +basic_ostringstream (27.7.3 [ostringstream]) are inconsistent +in their definition of the type traits_type: For +istringstream, this type is defined, for the other two it is +not. This should be consistent.
+ + +Proposed resolution:
+Proposed resolution:
To the declarations of +basic_ostringstream (27.7.3 [ostringstream]) and +basic_stringstream (27.7.4 [stringstream]) add:
+++ + + + +typedef traits traits_type;+
Section: 27.8.1.5 [filebuf.virtuals] Status: WP + Submitter: Dietmar Kühl Date: 1999-07-20
+View all other issues in [filebuf.virtuals].
+View all issues with WP status.
+Discussion:
+Overridden virtual functions, seekpos()
In 27.8.1.1 [filebuf] paragraph 3, it is stated that a joint input and +output position is maintained by basic_filebuf. Still, the +description of seekpos() seems to talk about different file +positions. In particular, it is unclear (at least to me) what is +supposed to happen to the output buffer (if there is one) if only the +input position is changed. The standard seems to mandate that the +output buffer is kept and processed as if there was no positioning of +the output position (by changing the input position). Of course, this +can be exactly what you want if the flag ios_base::ate is +set. However, I think, the standard should say something like +this:
+Plus the appropriate error handling, that is...
+ + +Proposed resolution:
+Change the unnumbered paragraph in 27.8.1.4 (lib.filebuf.virtuals) before +paragraph 14 from:
+++pos_type seekpos(pos_type sp, ios_base::openmode = ios_base::in | + ios_base::out);
+Alters the file position, if possible, to correspond to the position stored + in sp (as described below).
+- if (which&ios_base::in)!=0, set the file position to sp, then update + the input sequence
+- if (which&ios_base::out)!=0, then update the output sequence, write + any unshift sequence, and set the file position to sp.
+
to:
+++ +pos_type seekpos(pos_type sp, ios_base::openmode = ios_base::in | + ios_base::out);
+Alters the file position, if possible, to correspond to the position stored + in sp (as described below). Altering the file position performs as follows:
+1. if (om & ios_base::out)!=0, then update the output sequence and + write any unshift sequence;
+2. set the file position to sp;
+3. if (om & ios_base::in)!=0, then update the input sequence;
+where om is the open mode passed to the last call to open(). The operation + fails if is_open() returns false.
+
[Kona: Dietmar is working on a proposed resolution.]
+ +[Post-Tokyo: Dietmar supplied the above wording.]
+ + + + + + +Section: 27.6.1.3 [istream.unformatted] Status: TC + Submitter: Greg Comeau, Dietmar Kühl Date: 1999-07-23
+View all other issues in [istream.unformatted].
+View all issues with TC status.
+Discussion:
+In 27.6.1.1 [istream] the function +ignore() gets an object of type streamsize as first +argument. However, in 27.6.1.3 [istream.unformatted] +paragraph 23 the first argument is of type int.
+ +As far as I can see this is not really a contradiction because +everything is consistent if streamsize is typedef to be +int. However, this is almost certainly not what was +intended. The same thing happened to basic_filebuf::setbuf(), +as described in issue 173.
+ +Darin Adler also +submitted this issue, commenting: Either 27.6.1.1 should be modified +to show a first parameter of type int, or 27.6.1.3 should be modified +to show a first parameter of type streamsize and use +numeric_limits<streamsize>::max.
+ + +Proposed resolution:
+In 27.6.1.3 [istream.unformatted] paragraph 23 and 24, change both uses +of int in the description of ignore() to +streamsize.
+ + + + +Section: 27.8.1.5 [filebuf.virtuals] Status: TC + Submitter: Greg Comeau, Dietmar Kühl Date: 1999-07-23
+View all other issues in [filebuf.virtuals].
+View all issues with TC status.
+Discussion:
+ ++In 27.8.1.1 [filebuf] the function setbuf() gets an +object of type streamsize as second argument. However, in +27.8.1.5 [filebuf.virtuals] paragraph 9 the second argument is of type +int. +
+ ++As far as I can see this is not really a contradiction because +everything is consistent if streamsize is typedef to be +int. However, this is almost certainly not what was +intended. The same thing happened to basic_istream::ignore(), +as described in issue 172. +
+ + + +Proposed resolution:
+In 27.8.1.5 [filebuf.virtuals] paragraph 9, change all uses of +int in the description of setbuf() to +streamsize.
+ + + + +Section: D.6 [depr.ios.members] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-23
+View all other issues in [depr.ios.members].
+View all issues with TC status.
+Discussion:
+According to paragraph 1 of this section, streampos is the +type OFF_T, the same type as streamoff. However, in +paragraph 6 the streampos gets the type POS_T
+ + +Proposed resolution:
+Change D.6 [depr.ios.members] paragraph 1 from "typedef +OFF_T streampos;" to "typedef POS_T +streampos;"
+ + + + +Section: D.6 [depr.ios.members] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-23
+View all other issues in [depr.ios.members].
+View all issues with TC status.
+Discussion:
+According to paragraph 8 of this section, the methods +basic_streambuf::pubseekpos(), +basic_ifstream::open(), and basic_ofstream::open +"may" be overloaded by a version of this function taking the +type ios_base::open_mode as last argument argument instead of +ios_base::openmode (ios_base::open_mode is defined +in this section to be an alias for one of the integral types). The +clause specifies, that the last argument has a default argument in +three cases. However, this generates an ambiguity with the overloaded +version because now the arguments are absolutely identical if the last +argument is not specified.
+ + +Proposed resolution:
+In D.6 [depr.ios.members] paragraph 8, remove the default arguments for +basic_streambuf::pubseekpos(), +basic_ifstream::open(), and +basic_ofstream::open().
+ + + + +Section: D.6 [depr.ios.members] Status: TC + Submitter: Dietmar Kühl Date: 1999-07-23
+View all other issues in [depr.ios.members].
+View all issues with TC status.
+Discussion:
+The "overload" for the function exceptions() in +paragraph 8 gives the impression that there is another function of +this function defined in class ios_base. However, this is not +the case. Thus, it is hard to tell how the semantics (paragraph 9) can +be implemented: "Call the corresponding member function specified +in clause 27 [input.output]."
+ + +Proposed resolution:
+In D.6 [depr.ios.members] paragraph 8, move the declaration of the +function exceptions()into class basic_ios.
+ + + + +Section: 23.1 [container.requirements] Status: WP + Submitter: Judy Ward Date: 1998-07-02
+View other active issues in [container.requirements].
+View all other issues in [container.requirements].
+View all issues with WP status.
+Discussion:
+Currently the following will not compile on two well-known standard +library implementations:
+ +++ +#include <set> +using namespace std; + +void f(const set<int> &s) +{ + set<int>::iterator i; + if (i==s.end()); // s.end() returns a const_iterator +}+
+The reason this doesn't compile is because operator== was implemented +as a member function of the nested classes set:iterator and +set::const_iterator, and there is no conversion from const_iterator to +iterator. Surprisingly, (s.end() == i) does work, though, because of +the conversion from iterator to const_iterator. +
+ ++I don't see a requirement anywhere in the standard that this must +work. Should there be one? If so, I think the requirement would need +to be added to the tables in section 24.1.1. I'm not sure about the +wording. If this requirement existed in the standard, I would think +that implementors would have to make the comparison operators +non-member functions.
+ +This issues was also raised on comp.std.c++ by Darin +Adler. The example given was:
+ +++ +bool check_equal(std::deque<int>::iterator i, +std::deque<int>::const_iterator ci) +{ +return i == ci; +}+
Comment from John Potter:
+++ + ++ In case nobody has noticed, accepting it will break reverse_iterator. +
+ ++ The fix is to make the comparison operators templated on two types. +
+ +template <class Iterator1, class Iterator2> + bool operator== (reverse_iterator<Iterator1> const& x, + reverse_iterator<Iterator2> const& y); ++ ++ Obviously: return x.base() == y.base(); +
+ ++ Currently, no reverse_iterator to const_reverse_iterator compares are + valid. +
+ ++ BTW, I think the issue is in support of bad code. Compares should be + between two iterators of the same type. All std::algorithms require + the begin and end iterators to be of the same type. +
+
Proposed resolution:
+Insert this paragraph after 23.1 [container.requirements] paragraph 7:
+++ +In the expressions
+i == j + i != j + i < j + i <= j + i >= j + i > j + i - j ++Where i and j denote objects of a container's iterator type, + either or both may be replaced by an object of the container's + const_iterator type referring to the same element with no + change in semantics.
+
[post-Toronto: Judy supplied a proposed resolution saying that +iterator and const_iterator could be freely mixed in +iterator comparison and difference operations.]
+ + +[Redmond: Dave and Howard supplied a new proposed resolution which +explicitly listed expressions; there was concern that the previous +proposed resolution was too informal.]
+ + + +Rationale:
++The LWG believes it is clear that the above wording applies only to +the nested types X::iterator and X::const_iterator, +where X is a container. There is no requirement that +X::reverse_iterator and X::const_reverse_iterator +can be mixed. If mixing them is considered important, that's a +separate issue. (Issue 280.) +
+ + + + +Section: 20.2.3 [pairs] Status: TC + Submitter: Andrew Koenig Date: 1999-08-03
+View all other issues in [pairs].
+View all issues with TC status.
+Discussion:
+The claim has surfaced in Usenet that expressions such as
+
+ make_pair("abc", 3)
+
+are illegal, notwithstanding their use in examples, because template instantiation tries to bind the first template
+parameter to const char (&)[4], which type is uncopyable.
+
+I doubt anyone intended that behavior...
+
Proposed resolution:
+In 20.2 [utility], paragraph 1 change the following +declaration of make_pair():
+++template <class T1, class T2> pair<T1,T2> make_pair(const T1&, const T2&);+
to:
+++template <class T1, class T2> pair<T1,T2> make_pair(T1, T2);+
In 20.2.3 [pairs] paragraph 7 and the line before, change:
+++template <class T1, class T2> +pair<T1, T2> make_pair(const T1& x, const T2& y);+
to:
+++template <class T1, class T2> +pair<T1, T2> make_pair(T1 x, T2 y);+
and add the following footnote to the effects clause:
+++ + +According to 12.8 [class.copy], an implementation is permitted + to not perform a copy of an argument, thus avoiding unnecessary + copies.
+
Rationale:
+Two potential fixes were suggested by Matt Austern and Dietmar +Kühl, respectively, 1) overloading with array arguments, and 2) use of +a reference_traits class with a specialization for arrays. Andy +Koenig suggested changing to pass by value. In discussion, it appeared +that this was a much smaller change to the standard that the other two +suggestions, and any efficiency concerns were more than offset by the +advantages of the solution. Two implementors reported that the +proposed resolution passed their test suites.
+ + + + +Section: 17 [library] Status: WP + Submitter: Al Stevens Date: 1999-08-15
+View all other issues in [library].
+View all issues with WP status.
+Discussion:
+Many references to size_t throughout the document +omit the std:: namespace qualification.
For +example, 17.4.3.5 [replacement.functions] paragraph 2:
+++ + +operator new(size_t) + operator new(size_t, const std::nothrow_t&) + operator new[](size_t) + operator new[](size_t, const std::nothrow_t&)+
Proposed resolution:
+In 17.4.3.5 [replacement.functions] paragraph 2: replace:
+++- operator new(size_t)
+
+ - operator new(size_t, const std::nothrow_t&)
+ - operator new[](size_t)
+ - operator new[](size_t, const std::nothrow_t&)
by:
+++- operator new(std::size_t) +- operator new(std::size_t, const std::nothrow_t&) +- operator new[](std::size_t) +- operator new[](std::size_t, const std::nothrow_t&)+
In [lib.allocator.requirements] 20.1.5, paragraph 4: replace:
+++The typedef members pointer, const_pointer, size_type, and difference_type + are required to be T*, T const*, size_t, and ptrdiff_t, respectively.
+
by:
+++The typedef members pointer, const_pointer, size_type, and difference_type + are required to be T*, T const*, std::size_t, and std::ptrdiff_t, + respectively.
+
In [lib.allocator.members] 20.4.1.1, paragraphs 3 and 6: replace:
+++3 Notes: Uses ::operator new(size_t) (18.4.1).
+6 Note: the storage is obtained by calling ::operator new(size_t), but it + is unspecified when or how often this function is called. The use of hint is + unspecified, but intended as an aid to locality if an implementation so + desires.
+
by:
+++3 Notes: Uses ::operator new(std::size_t) (18.4.1).
+6 Note: the storage is obtained by calling ::operator new(std::size_t), but + it is unspecified when or how often this function is called. The use of hint + is unspecified, but intended as an aid to locality if an implementation so + desires.
+
In [lib.char.traits.require] 21.1.1, paragraph 1: replace:
+++In Table 37, X denotes a Traits class defining types and functions for the + character container type CharT; c and d denote values of type CharT; p and q + denote values of type const CharT*; s denotes a value of type CharT*; n, i and + j denote values of type size_t; e and f denote values of type X::int_type; pos + denotes a value of type X::pos_type; and state denotes a value of type X::state_type.
+
by:
+++In Table 37, X denotes a Traits class defining types and functions for the + character container type CharT; c and d denote values of type CharT; p and q + denote values of type const CharT*; s denotes a value of type CharT*; n, i and + j denote values of type std::size_t; e and f denote values of type X::int_type; + pos denotes a value of type X::pos_type; and state denotes a value of type X::state_type.
+
In [lib.char.traits.require] 21.1.1, table 37: replace the return type of +X::length(p): "size_t" by "std::size_t".
+ In [lib.std.iterator.tags] 24.3.3, paragraph 2: replace:
+ typedef ptrdiff_t difference_type;
+ by:
+ typedef std::ptrdiff_t difference_type;
In [lib.locale.ctype] 22.2.1.1 put namespace std { ...} around the
+declaration of template <class charT> class ctype.
+
+ In [lib.iterator.traits] 24.3.1, paragraph 2 put namespace std { ...} around the declaration of:
+
+ template<class Iterator> struct iterator_traits
+ template<class T> struct iterator_traits<T*>
+ template<class T> struct iterator_traits<const T*>
Rationale:
+The LWG believes correcting names like size_t and +ptrdiff_t to std::size_t and std::ptrdiff_t +to be essentially editorial. There there can't be another size_t or +ptrdiff_t meant anyway because, according to 17.4.3.2.4 [extern.types],
+ ++ ++For each type T from the Standard C library, the types ::T and std::T +are reserved to the implementation and, when defined, ::T shall be +identical to std::T. +
The issue is treated as a Defect Report to make explicit the Project +Editor's authority to make this change.
+ +[Post-Tokyo: Nico Josuttis provided the above wording at the +request of the LWG.]
+ + +[Toronto: This is tangentially related to issue 229, but only tangentially: the intent of this issue is to +address use of the name size_t in contexts outside of +namespace std, such as in the description of ::operator new. +The proposed changes should be reviewed to make sure they are +correct.]
+ + +[pre-Copenhagen: Nico has reviewed the changes and believes +them to be correct.]
+ + + + + + + +Section: 27.6.3 [std.manip] Status: WP + Submitter: Andy Sawyer Date: 1999-07-07
+View all other issues in [std.manip].
+View all issues with WP status.
+Discussion:
+27.6.3 [std.manip] paragraph 3 says (clause numbering added for +exposition):
+++Returns: An object s of unspecified type such that if [1] out is an (instance +of) basic_ostream then the expression out<<s behaves as if f(s) were +called, and if [2] in is an (instance of) basic_istream then the expression +in>>s behaves as if f(s) were called. Where f can be defined as: ios_base& +f(ios_base& str, ios_base::fmtflags mask) { // reset specified flags +str.setf(ios_base::fmtflags(0), mask); return str; } [3] The expression +out<<s has type ostream& and value out. [4] The expression in>>s +has type istream& and value in.
+
Given the definitions [1] and [2] for out and in, surely [3] should read: +"The expression out << s has type basic_ostream& ..." and +[4] should read: "The expression in >> s has type basic_istream& +..."
+If the wording in the standard is correct, I can see no way of implementing +any of the manipulators so that they will work with wide character streams.
+e.g. wcout << setbase( 16 );
+Must have value 'wcout' (which makes sense) and type 'ostream&' (which +doesn't).
+The same "cut'n'paste" type also seems to occur in Paras 4,5,7 and +8. In addition, Para 6 [setfill] has a similar error, but relates only to +ostreams.
+I'd be happier if there was a better way of saying this, to make it clear +that the value of the expression is "the same specialization of +basic_ostream as out"&
+ + +Proposed resolution:
+Replace section 27.6.3 [std.manip] except paragraph 1 with the +following:
+++ +2- The type designated smanip in each of the following function +descriptions is implementation-specified and may be different for each +function.
+
+
+smanip resetiosflags(ios_base::fmtflags mask);
+
+-3- Returns: An object s of unspecified type such that if out is an +instance of basic_ostream<charT,traits> then the expression +out<<s behaves +as if f(s, mask) were called, or if in is an instance of +basic_istream<charT,traits> then the expression in>>s +behaves as if +f(s, mask) were called. The function f can be defined as:*
+
+[Footnote: The expression cin >> resetiosflags(ios_base::skipws) +clears ios_base::skipws in the format flags stored in the +basic_istream<charT,traits> object cin (the same as cin >> +noskipws), and the expression cout << +resetiosflags(ios_base::showbase) clears +ios_base::showbase in the format flags stored in the +basic_ostream<charT,traits> object cout (the same as cout +<< +noshowbase). --- end footnote]
+
+ ios_base& f(ios_base& str, ios_base::fmtflags mask)
+ {
+ // reset specified flags
+ str.setf(ios_base::fmtflags(0), mask);
+ return str;
+ }
+
+The expression out<<s has type basic_ostream<charT,traits>& and value out. +The expression in>>s has type basic_istream<charT,traits>& and value in.
+
+ smanip setiosflags(ios_base::fmtflags mask);
+
+-4- Returns: An object s of unspecified type such that if out is an +instance of basic_ostream<charT,traits> then the expression +out<<s behaves +as if f(s, mask) were called, or if in is an instance of +basic_istream<charT,traits> then the expression in>>s +behaves as if f(s, +mask) were called. The function f can be defined as:
+
+ ios_base& f(ios_base& str, ios_base::fmtflags mask)
+ {
+ // set specified flags
+ str.setf(mask);
+ return str;
+ }
+
+The expression out<<s has type basic_ostream<charT,traits>& and value out. +The expression in>>s has type basic_istream<charT,traits>& and value in.
+
+smanip setbase(int base);
+
+-5- Returns: An object s of unspecified type such that if out is an +instance of basic_ostream<charT,traits> then the expression +out<<s behaves +as if f(s, base) were called, or if in is an instance of +basic_istream<charT,traits> then the expression in>>s +behaves as if f(s, +base) were called. The function f can be defined as:
+
+ ios_base& f(ios_base& str, int base)
+ {
+ // set basefield
+ str.setf(base == 8 ? ios_base::oct :
+ base == 10 ? ios_base::dec :
+ base == 16 ? ios_base::hex :
+ ios_base::fmtflags(0), ios_base::basefield);
+ return str;
+ }
+
+The expression out<<s has type basic_ostream<charT,traits>& and value out. +The expression in>>s has type basic_istream<charT,traits>& and value in.
+
+smanip setfill(char_type c);
+
+-6- Returns: An object s of unspecified type such that if out is (or is +derived from) basic_ostream<charT,traits> and c has type charT +then the +expression out<<s behaves as if f(s, c) were called. The function +f can be +defined as:
+
+ template<class charT, class traits>
+ basic_ios<charT,traits>& f(basic_ios<charT,traits>& str, charT c)
+ {
+ // set fill character
+ str.fill(c);
+ return str;
+ }
+
+The expression out<<s has type basic_ostream<charT,traits>& and value out.
+
+smanip setprecision(int n);
+
+-7- Returns: An object s of unspecified type such that if out is an +instance of basic_ostream<charT,traits> then the expression +out<<s behaves +as if f(s, n) were called, or if in is an instance of +basic_istream<charT,traits> then the expression in>>s +behaves as if f(s, n) +were called. The function f can be defined as:
+
+ ios_base& f(ios_base& str, int n)
+ {
+ // set precision
+ str.precision(n);
+ return str;
+ }
+
+The expression out<<s has type basic_ostream<charT,traits>& and value out. +The expression in>>s has type basic_istream<charT,traits>& and value in
+.
+smanip setw(int n);
+
+-8- Returns: An object s of unspecified type such that if out is an +instance of basic_ostream<charT,traits> then the expression +out<<s behaves +as if f(s, n) were called, or if in is an instance of +basic_istream<charT,traits> then the expression in>>s +behaves as if f(s, n) +were called. The function f can be defined as:
+
+ ios_base& f(ios_base& str, int n)
+ {
+ // set width
+ str.width(n);
+ return str;
+ }
+
+The expression out<<s has type +basic_ostream<charT,traits>& and value out. The expression +in>>s has type basic_istream<charT,traits>& and value +in. +
[Kona: Andy Sawyer and Beman Dawes will work to improve the wording of +the proposed resolution.]
+ + +[Tokyo - The LWG noted that issue 216 involves +the same paragraphs.]
+ + +[Post-Tokyo: The issues list maintainer combined the proposed +resolution of this issue with the proposed resolution for issue 216 as they both involved the same paragraphs, and were so +intertwined that dealing with them separately appear fraught with +error. The full text was supplied by Bill Plauger; it was cross +checked against changes supplied by Andy Sawyer. It should be further +checked by the LWG.]
+ + + + + + +Section: 18.2.1.5 [numeric.special] Status: WP + Submitter: Gabriel Dos Reis Date: 1999-07-21
+View all other issues in [numeric.special].
+View all issues with WP status.
+Discussion:
+bools are defined by the standard to be of integer types, as per +3.9.1 [basic.fundamental] paragraph 7. However "integer types" +seems to have a special meaning for the author of 18.2. The net effect +is an unclear and confusing specification for +numeric_limits<bool> as evidenced below.
+ +18.2.1.2/7 says numeric_limits<>::digits is, for built-in integer +types, the number of non-sign bits in the representation.
+ +4.5/4 states that a bool promotes to int ; whereas 4.12/1 says any non zero +arithmetical value converts to true.
+ +I don't think it makes sense at all to require +numeric_limits<bool>::digits and numeric_limits<bool>::digits10 to +be meaningful.
+ +The standard defines what constitutes a signed (resp. unsigned) integer +types. It doesn't categorize bool as being signed or unsigned. And the set of +values of bool type has only two elements.
+ +I don't think it makes sense to require numeric_limits<bool>::is_signed +to be meaningful.
+ +18.2.1.2/18 for numeric_limits<integer_type>::radix says:
+++ +For integer types, specifies the base of the representation.186)
+
This disposition is at best misleading and confusing for the standard +requires a "pure binary numeration system" for integer types as per +3.9.1/7
+ +The footnote 186) says: "Distinguishes types with base other than 2 (e.g +BCD)." This also erroneous as the standard never defines any integer +types with base representation other than 2.
+ +Furthermore, numeric_limits<bool>::is_modulo and +numeric_limits<bool>::is_signed have similar problems.
+ + +Proposed resolution:
+Append to the end of 18.2.1.5 [numeric.special]:
+++ +The specialization for bool shall be provided as follows:
+namespace std { + template<> class numeric_limits<bool> { + public: + static const bool is_specialized = true; + static bool min() throw() { return false; } + static bool max() throw() { return true; } + + static const int digits = 1; + static const int digits10 = 0; + static const bool is_signed = false; + static const bool is_integer = true; + static const bool is_exact = true; + static const int radix = 2; + static bool epsilon() throw() { return 0; } + static bool round_error() throw() { return 0; } + + static const int min_exponent = 0; + static const int min_exponent10 = 0; + static const int max_exponent = 0; + static const int max_exponent10 = 0; + + static const bool has_infinity = false; + static const bool has_quiet_NaN = false; + static const bool has_signaling_NaN = false; + static const float_denorm_style has_denorm = denorm_absent; + static const bool has_denorm_loss = false; + static bool infinity() throw() { return 0; } + static bool quiet_NaN() throw() { return 0; } + static bool signaling_NaN() throw() { return 0; } + static bool denorm_min() throw() { return 0; } + + static const bool is_iec559 = false; + static const bool is_bounded = true; + static const bool is_modulo = false; + + static const bool traps = false; + static const bool tinyness_before = false; + static const float_round_style round_style = round_toward_zero; + }; + }+
[Tokyo: The LWG desires wording that specifies exact values +rather than more general wording in the original proposed +resolution.]
+ + +[Post-Tokyo: At the request of the LWG in Tokyo, Nico +Josuttis provided the above wording.]
+ + + + + + +Section: 20.6 [function.objects] Status: WP + Submitter: UK Panel Date: 1999-07-26
+View all other issues in [function.objects].
+View all issues with WP status.
+Discussion:
+Paragraph 4 of 20.6 [function.objects] says:
+++[Example: To negate every element of a: transform(a.begin(), a.end(), + a.begin(), negate<double>()); The corresponding functions will inline + the addition and the negation. end example]
+
(Note: The "addition" referred to in the above is in para 3) we can +find no other wording, except this (non-normative) example which suggests that +any "inlining" will take place in this case.
+Indeed both:
+++17.4.4.3 Global Functions [lib.global.functions] 1 It is + unspecified whether any global functions in the C++ Standard Library + are defined as inline (7.1.2).
+
and
+++17.4.4.4 Member Functions [lib.member.functions] 1 It is + unspecified whether any member functions in the C++ Standard Library + are defined as inline (7.1.2).
+
take care to state that this may indeed NOT be the case.
+Thus the example "mandates" behavior that is explicitly +not required elsewhere.
+ + +Proposed resolution:
+In 20.6 [function.objects] paragraph 1, remove the sentence:
+++They are important for the effective use of the library.
+
Remove 20.6 [function.objects] paragraph 2, which reads:
+++Using function objects together with function templates + increases the expressive power of the library as well as making the + resulting code much more efficient.
+
In 20.6 [function.objects] paragraph 4, remove the sentence:
+++ +The corresponding functions will inline the addition and the + negation.
+
[Kona: The LWG agreed there was a defect.]
+ +[Tokyo: The LWG crafted the proposed resolution.]
+ + + + + + +Section: 23.3.5.2 [bitset.members] Status: WP + Submitter: Darin Adler Date: 1999-08-13
+View all other issues in [bitset.members].
+View all issues with WP status.
+Discussion:
+In section 23.3.5.2 [bitset.members], paragraph 13 defines the +bitset::set operation to take a second parameter of type int. The +function tests whether this value is non-zero to determine whether to +set the bit to true or false. The type of this second parameter should +be bool. For one thing, the intent is to specify a Boolean value. For +another, the result type from test() is bool. In addition, it's +possible to slice an integer that's larger than an int. This can't +happen with bool, since conversion to bool has the semantic of +translating 0 to false and any non-zero value to true.
+ + +Proposed resolution:
+In 23.3.5 [template.bitset] Para 1 Replace:
+++bitset<N>& set(size_t pos, int val = true );+
With:
+++bitset<N>& set(size_t pos, bool val = true );+
In 23.3.5.2 [bitset.members] Para 12(.5) Replace:
+++bitset<N>& set(size_t pos, int val = 1 );+
With:
+++ +bitset<N>& set(size_t pos, bool val = true );+
[Kona: The LWG agrees with the description. Andy Sawyer will work +on better P/R wording.]
+ +[Post-Tokyo: Andy provided the above wording.]
+ + + +Rationale:
+bool is a better choice. It is believed that binary +compatibility is not an issue, because this member function is +usually implemented as inline, and because it is already +the case that users cannot rely on the type of a pointer to a +nonvirtual member of a standard library class.
+ + + + + +Section: 25.2.3 [alg.swap] Status: WP + Submitter: Andrew Koenig Date: 1999-08-14
+View all other issues in [alg.swap].
+View all issues with WP status.
+Discussion:
+The description of iter_swap in 25.2.2 paragraph 7,says that it
+``exchanges the values'' of the objects to which two iterators
+refer.
What it doesn't say is whether it does so using swap
+or using the assignment operator and copy constructor.
This
+question is an important one to answer, because swap is specialized to
+work efficiently for standard containers.
For example:
++vector<int> v1, v2; +iter_swap(&v1, &v2);+
Is this call to iter_swap equivalent to calling swap(v1, v2)? +Or is it equivalent to
+++{ +vector<int> temp = v1; +v1 = v2; +v2 = temp; +}+
The first alternative is O(1); the second is O(n).
+A LWG member, Dave Abrahams, comments:
+++ +Not an objection necessarily, but I want to point out the cost of +that requirement:
+++iter_swap(list<T>::iterator, list<T>::iterator)
+can currently be specialized to be more efficient than +iter_swap(T*,T*) for many T (by using splicing). Your proposal would +make that optimization illegal.
+
[Kona: The LWG notes the original need for iter_swap was proxy iterators +which are no longer permitted.]
+ + + +Proposed resolution:
+Change the effect clause of iter_swap in 25.2.2 paragraph 7 from:
+++Exchanges the values pointed to by the two iterators a and b.
+
to
+++ + + +swap(*a, *b).
+
Rationale:
+It's useful to say just what iter_swap does. There may be + some iterators for which we want to specialize iter_swap, + but the fully general version should have a general specification.
+ +Note that in the specific case of list<T>::iterator, +iter_swap should not be specialized as suggested above. That would do +much more than exchanging the two iterators' values: it would change +predecessor/successor relationships, possibly moving the iterator from +one list to another. That would surely be inappropriate.
+ + + + + +Section: 27.4.2.2 [fmtflags.state] Status: TC + Submitter: Andrew Koenig Date: 1999-08-25
+View all other issues in [fmtflags.state].
+View all issues with TC status.
+Discussion:
+27.4.2.2 paragraph 9 claims that setprecision() sets the precision,
+and includes a parenthetical note saying that it is the number of
+digits after the decimal point.
+
+This claim is not strictly correct. For example, in the default
+floating-point output format, setprecision sets the number of
+significant digits printed, not the number of digits after the decimal
+point.
+
+I would like the committee to look at the definition carefully and
+correct the statement in 27.4.2.2
Proposed resolution:
+Remove from 27.4.2.2 [fmtflags.state], paragraph 9, the text +"(number of digits after the decimal point)".
+ + + + +Section: 25.3.6 [alg.heap.operations] Status: TC + Submitter: Markus Mauhart Date: 1999-09-24
+View all issues with TC status.
+Duplicate of: 216
+Discussion:
+25.3.6 [lib.alg.heap.operations] states two key properties of a heap [a,b), the first of them
+is
+
+ `"(1) *a is the largest element"
+
+I think this is incorrect and should be changed to the wording in the proposed
+resolution.
Actually there are two independent changes:
+++ + +A-"part of largest equivalence class" instead of "largest", cause 25.3 + [lib.alg.sorting] asserts "strict weak ordering" for all its sub clauses.
+B-Take +'an oldest' from that equivalence class, otherwise the heap functions +could not be used for a priority queue as explained in 23.2.3.2.2 +[lib.priqueue.members] (where I assume that a "priority queue" respects +priority AND time).
+
Proposed resolution:
+Change 25.3.6 [alg.heap.operations] property (1) from:
+++(1) *a is the largest element
+
to:
+++ + + + + +(1) There is no element greater than *a
+
Section: 27.6.1.1.3 [istream::sentry] Status: TC + Submitter: Matt Austern Date: 1999-10-13
+View all other issues in [istream::sentry].
+View all issues with TC status.
+Discussion:
+Suppose that is.flags() & ios_base::skipws is nonzero. +What should basic_istream<>::sentry's constructor do if it +reaches eof while skipping whitespace? 27.6.1.1.2/5 suggests it +should set failbit. Should it set eofbit as well? The standard +doesn't seem to answer that question.
+ +On the one hand, nothing in 27.6.1.1.3 [istream::sentry] says that +basic_istream<>::sentry should ever set eofbit. On the +other hand, 27.6.1.1 [istream] paragraph 4 says that if +extraction from a streambuf "returns +traits::eof(), then the input function, except as explicitly +noted otherwise, completes its actions and does +setstate(eofbit)". So the question comes down to +whether basic_istream<>::sentry's constructor is an +input function.
+ +Comments from Jerry Schwarz:
+++ + +It was always my intention that eofbit should be set any time that a +virtual returned something to indicate eof, no matter what reason +iostream code had for calling the virtual.
++The motivation for this is that I did not want to require streambufs +to behave consistently if their virtuals are called after they have +signaled eof.
++The classic case is a streambuf reading from a UNIX file. EOF isn't +really a state for UNIX file descriptors. The convention is that a +read on UNIX returns 0 bytes to indicate "EOF", but the file +descriptor isn't shut down in any way and future reads do not +necessarily also return 0 bytes. In particular, you can read from +tty's on UNIX even after they have signaled "EOF". (It +isn't always understood that a ^D on UNIX is not an EOF indicator, but +an EOL indicator. By typing a "line" consisting solely of +^D you cause a read to return 0 bytes, and by convention this is +interpreted as end of file.)
+
Proposed resolution:
+Add a sentence to the end of 27.6.1.1.2 paragraph 2:
+++ + + + +If is.rdbuf()->sbumpc() or is.rdbuf()->sgetc() +returns traits::eof(), the function calls +setstate(failbit | eofbit) (which may throw +ios_base::failure). +
+
Section: 24.1 [iterator.requirements] Status: WP + Submitter: Beman Dawes Date: 1999-11-03
+View other active issues in [iterator.requirements].
+View all other issues in [iterator.requirements].
+View all issues with WP status.
+Discussion:
++Is a pointer or reference obtained from an iterator still valid after +destruction of the iterator? +
++Is a pointer or reference obtained from an iterator still valid after the value +of the iterator changes? +
+++ +#include <iostream> +#include <vector> +#include <iterator> + +int main() +{ + typedef std::vector<int> vec_t; + vec_t v; + v.push_back( 1 ); + + // Is a pointer or reference obtained from an iterator still + // valid after destruction of the iterator? + int * p = &*v.begin(); + std::cout << *p << '\n'; // OK? + + // Is a pointer or reference obtained from an iterator still + // valid after the value of the iterator changes? + vec_t::iterator iter( v.begin() ); + p = &*iter++; + std::cout << *p << '\n'; // OK? + + return 0; +} ++
The standard doesn't appear to directly address these +questions. The standard needs to be clarified. At least two real-world +cases have been reported where library implementors wasted +considerable effort because of the lack of clarity in the +standard. The question is important because requiring pointers and +references to remain valid has the effect for practical purposes of +prohibiting iterators from pointing to cached rather than actual +elements of containers.
+ +The standard itself assumes that pointers and references obtained +from an iterator are still valid after iterator destruction or +change. The definition of reverse_iterator::operator*(), 24.4.1.3.3 [reverse.iter.conv], which returns a reference, defines +effects:
+ +++Iterator tmp = current; +return *--tmp;+
The definition of reverse_iterator::operator->(), 24.4.1.3.4 +[reverse.iter.op.star], which returns a pointer, defines effects:
+++ +return &(operator*());+
Because the standard itself assumes pointers and references remain +valid after iterator destruction or change, the standard should say so +explicitly. This will also reduce the chance of user code breaking +unexpectedly when porting to a different standard library +implementation.
+ + +Proposed resolution:
+Add a new paragraph to 24.1 [iterator.requirements]:
++ ++Destruction of an iterator may invalidate pointers and references +previously obtained from that iterator. +
Replace paragraph 1 of 24.4.1.3.3 [reverse.iter.conv] with:
+ +++ +Effects:
+this->tmp = current; + --this->tmp; + return *this->tmp; ++ ++[Note: This operation must use an auxiliary member variable, +rather than a temporary variable, to avoid returning a reference that +persists beyond the lifetime of its associated iterator. (See +24.1 [iterator.requirements].) The name of this member variable is shown for +exposition only. --end note] +
+
[Post-Tokyo: The issue has been reformulated purely +in terms of iterators.]
+ + +[Pre-Toronto: Steve Cleary pointed out the no-invalidation +assumption by reverse_iterator. The issue and proposed resolution was +reformulated yet again to reflect this reality.]
+ + +[Copenhagen: Steve Cleary pointed out that reverse_iterator +assumes its underlying iterator has persistent pointers and +references. Andy Koenig pointed out that it is possible to rewrite +reverse_iterator so that it no longer makes such an assupmption. +However, this issue is related to issue 299. If we +decide it is intentional that p[n] may return by value +instead of reference when p is a Random Access Iterator, +other changes in reverse_iterator will be necessary.]
+ + + +Rationale:
+This issue has been discussed extensively. Note that it is +not an issue about the behavior of predefined iterators. It is +asking whether or not user-defined iterators are permitted to have +transient pointers and references. Several people presented examples +of useful user-defined iterators that have such a property; examples +include a B-tree iterator, and an "iota iterator" that doesn't point +to memory. Library implementors already seem to be able to cope with +such iterators: they take pains to avoid forming references to memory +that gets iterated past. The only place where this is a problem is +reverse_iterator, so this issue changes +reverse_iterator to make it work.
+ +This resolution does not weaken any guarantees provided by +predefined iterators like list<int>::iterator. +Clause 23 should be reviewed to make sure that guarantees for +predefined iterators are as strong as users expect.
+ + + + + + +Section: 20.1.2 [allocator.requirements] Status: TC + Submitter: Matt Austern Date: 1999-11-19
+View other active issues in [allocator.requirements].
+View all other issues in [allocator.requirements].
+View all issues with TC status.
+Discussion:
++Suppose that A is a class that conforms to the +Allocator requirements of Table 32, and a is an +object of class A What should be the return +value of a.allocate(0)? Three reasonable +possibilities: forbid the argument 0, return +a null pointer, or require that the return value be a +unique non-null pointer. +
+ + +Proposed resolution:
++Add a note to the allocate row of Table 32: +"[Note: If n == 0, the return value is unspecified. --end note]"
+ + +Rationale:
+A key to understanding this issue is that the ultimate use of +allocate() is to construct an iterator, and that iterator for zero +length sequences must be the container's past-the-end +representation. Since this already implies special case code, it +would be over-specification to mandate the return value. +
+ + + + +Section: 24.1.3 [forward.iterators] Status: WP + Submitter: Matt Austern Date: 1999-11-19
+View all other issues in [forward.iterators].
+View all issues with WP status.
+Discussion:
++In table 74, the return type of the expression *a is given +as T&, where T is the iterator's value type. +For constant iterators, however, this is wrong. ("Value type" +is never defined very precisely, but it is clear that the value type +of, say, std::list<int>::const_iterator is supposed to be +int, not const int.) +
+ + +Proposed resolution:
++In table 74, in the *a and *r++ rows, change the +return type from "T&" to "T& +if X is mutable, otherwise const T&". +In the a->m row, change the return type from +"U&" to "U& if X is mutable, +otherwise const U&". +
+ +[Tokyo: The LWG believes this is the tip of a larger iceberg; +there are multiple const problems with the STL portion of the library +and that these should be addressed as a single package. Note +that issue 180 has already been declared NAD Future for +that very reason.]
+ + +[Redmond: the LWG thinks this is separable from other constness +issues. This issue is just cleanup; it clarifies language that was +written before we had iterator_traits. Proposed resolution was +modified: the original version only discussed *a. It was pointed out +that we also need to worry about *r++ and a->m.]
+ + + + + + + +Section: 18.2.1 [limits] Status: WP + Submitter: Stephen Cleary Date: 1999-12-21
+View all other issues in [limits].
+View all issues with WP status.
+Discussion:
++In some places in this section, the terms "fundamental types" and +"scalar types" are used when the term "arithmetic types" is intended. +The current usage is incorrect because void is a fundamental type and +pointers are scalar types, neither of which should have +specializations of numeric_limits. +
+[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.]
+ + + +Proposed resolution:
+ ++Change 18.2 [support.limits] to: +
+ +++ ++-1- The headers <limits>, <climits>, +<cfloat>, and <cinttypes> supply +characteristics of implementation-dependent
+fundamental+arithmetic types (3.9.1). +
+Change 18.2.1 [limits] to: +
+ +++ ++-1- The numeric_limits component provides a C++ program with +information about various properties of the implementation's +representation of the
+fundamentalarithmetic +types. ++-2- Specializations shall be provided for each
+fundamental+arithmetic type, both floating point and integer, including +bool. The member is_specialized shall be true +for all such specializations of numeric_limits. ++-4- Non-
+fundamentalarithmetic standard types, such +as complex<T> (26.3.2), shall not have specializations. +
+Change 18.2.1.1 [numeric.limits] to: +
+ +++ + + + + + ++
+-1- The member is_specialized makes it possible to distinguish +between fundamental types, which have specializations, and non-scalar types, +which do not.+
Section: 25.2.9 [alg.unique] Status: WP + Submitter: Andrew Koenig Date: 2000-01-13
+View all other issues in [alg.unique].
+View all issues with WP status.
+Discussion:
++What should unique() do if you give it a predicate that is not an +equivalence relation? There are at least two plausible answers: +
+ ++ ++ ++ 1. You can't, because 25.2.8 says that it it "eliminates all but + the first element from every consecutive group of equal + elements..." and it wouldn't make sense to interpret "equal" as + meaning anything but an equivalence relation. [It also doesn't + make sense to interpret "equal" as meaning ==, because then there + would never be any sense in giving a predicate as an argument at + all.] +
+ ++ 2. The word "equal" should be interpreted to mean whatever the + predicate says, even if it is not an equivalence relation + (and in particular, even if it is not transitive). +
+ +
+The example that raised this question is from Usenet: +
+ ++ ++ +int f[] = { 1, 3, 7, 1, 2 }; +int* z = unique(f, f+5, greater<int>());+ +
+If one blindly applies the definition using the predicate +greater<int>, and ignore the word "equal", you get: +
+ ++ ++ ++ Eliminates all but the first element from every consecutive group + of elements referred to by the iterator i in the range [first, last) + for which *i > *(i - 1). +
+ +
+The first surprise is the order of the comparison. If we wanted to
+allow for the predicate not being an equivalence relation, then we
+should surely compare elements the other way: pred(*(i - 1), *i). If
+we do that, then the description would seem to say: "Break the
+sequence into subsequences whose elements are in strictly increasing
+order, and keep only the first element of each subsequence". So the
+result would be 1, 1, 2. If we take the description at its word, it
+would seem to call for strictly DEcreasing order, in which case the
+result should be 1, 3, 7, 2.
+
+In fact, the SGI implementation of unique() does neither: It yields 1,
+3, 7.
+
Proposed resolution:
+Change 25.2.9 [alg.unique] paragraph 1 to:
++ ++For a nonempty range, eliminates all but the first element from every +consecutive group of equivalent elements referred to by the iterator +i in the range [first+1, last) for which the following +conditions hold: *(i-1) == *i or pred(*(i-1), *i) != +false. +
+Also insert a new paragraph, paragraph 2a, that reads: "Requires: The +comparison function must be an equivalence relation." +
+ +[Redmond: discussed arguments for and against requiring the +comparison function to be an equivalence relation. Straw poll: +14-2-5. First number is to require that it be an equivalence +relation, second number is to explicitly not require that it be an +equivalence relation, third number is people who believe they need +more time to consider the issue. A separate issue: Andy Sawyer +pointed out that "i-1" is incorrect, since "i" can refer to the first +iterator in the range. Matt provided wording to address this +problem.]
+ + +[Curaçao: The LWG changed "... the range (first, +last)..." to "... the range [first+1, last)..." for +clarity. They considered this change close enough to editorial to not +require another round of review.]
+ + + + +Rationale:
+The LWG also considered an alternative resolution: change +25.2.9 [alg.unique] paragraph 1 to:
+ ++ ++For a nonempty range, eliminates all but the first element from every +consecutive group of elements referred to by the iterator +i in the range (first, last) for which the following +conditions hold: *(i-1) == *i or pred(*(i-1), *i) != +false. +
+Also insert a new paragraph, paragraph 1a, that reads: "Notes: The +comparison function need not be an equivalence relation." +
+ + +Informally: the proposed resolution imposes an explicit requirement +that the comparison function be an equivalence relation. The +alternative resolution does not, and it gives enough information so +that the behavior of unique() for a non-equivalence relation is +specified. Both resolutions are consistent with the behavior of +existing implementations.
+ + + + + +Section: 18.5.1.1 [new.delete.single] Status: WP + Submitter: Howard Hinnant Date: 1999-08-29
+View all other issues in [new.delete.single].
+View all issues with WP status.
+Discussion:
+As specified, the implementation of the nothrow version of operator +new does not necessarily call the ordinary operator new, but may +instead simply call the same underlying allocator and return a null +pointer instead of throwing an exception in case of failure.
+ +Such an implementation breaks code that replaces the ordinary +version of new, but not the nothrow version. If the ordinary version +of new/delete is replaced, and if the replaced delete is not +compatible with pointers returned from the library versions of new, +then when the replaced delete receives a pointer allocated by the +library new(nothrow), crash follows.
+ +The fix appears to be that the lib version of new(nothrow) must +call the ordinary new. Thus when the ordinary new gets replaced, the +lib version will call the replaced ordinary new and things will +continue to work.
+ +An alternative would be to have the ordinary new call +new(nothrow). This seems sub-optimal to me as the ordinary version of +new is the version most commonly replaced in practice. So one would +still need to replace both ordinary and nothrow versions if one wanted +to replace the ordinary version.
+ +Another alternative is to put in clear text that if one version is +replaced, then the other must also be replaced to maintain +compatibility. Then the proposed resolution below would just be a +quality of implementation issue. There is already such text in +paragraph 7 (under the new(nothrow) version). But this nuance is +easily missed if one reads only the paragraphs relating to the +ordinary new.
+ ++N2158 +has been written explaining the rationale for the proposed resolution below. +
+ + + +Proposed resolution:
++Change 18.5.1.1 [new.delete.single]: +
+ +++ +void* operator new(std::size_t size, const std::nothrow_t&) throw(); ++++ ++-5- Effects: Same as above, except that it is called by a placement +version of a new-expression when a C++ program prefers a null pointer result as +an error indication, instead of a bad_alloc exception. +
+ ++-6- Replaceable: a C++ program may define a function with this function +signature that displaces the default version defined by the C++ Standard +library. +
+ ++-7- Required behavior: Return a non-null pointer to suitably aligned +storage (3.7.4), or else return a null pointer. This nothrow version of operator +new returns a pointer obtained as if acquired from the (possibly +replaced) ordinary version. This requirement is binding on a replacement +version of this function. +
+ ++-8- Default behavior: +
++
+- +Calls operator new(size). +
+- +If the call to operator new(size) returns normally, returns +the result of that call, else +
+- +if the call to operator new(size) throws an exception, returns +a null pointer. +
+- +
+Executes a loop: Within the loop, the function first attempts to allocate the +requested storage. Whether the attempt involves a call to the Standard C library +function malloc is unspecified. +- +
+Returns a pointer to the allocated storage if the attempt is successful. +Otherwise, if the last argument to set_new_handler() was a null +pointer, return a null pointer. +- +
+Otherwise, the function calls the current new_handler (18.5.2.2). If the +called function returns, the loop repeats. +- +
+The loop terminates when an attempt to allocate the requested storage is +successful or when a called new_handler function does not return. If the +called new_handler function terminates by throwing a bad_alloc +exception, the function returns a null pointer. ++-9- [Example: +
++T* p1 = new T; // throws bad_alloc if it fails +T* p2 = new(nothrow) T; // returns 0 if it fails ++--end example] +
+void operator delete(void* ptr) throw(); ++ +void operator delete(void* ptr, const std::nothrow_t&) throw();+++ ++-10- Effects: The deallocation function (3.7.4.2) called by a +delete-expression to render the value of ptr invalid. +
++-11- Replaceable: a C++ program may define a function with this function +signature that displaces the default version defined by the C++ Standard +library. +
++-12- Requires: the value of ptr is null or the value +returned by an earlier call to the
+default(possibly +replaced) operator new(std::size_t) or operator +new(std::size_t, const std::nothrow_t&). ++-13- Default behavior: +
++
+- +For a null value of ptr, do nothing. +
+- +Any other value of ptr shall be a value returned earlier by a +call to the default operator new, which was not invalidated by an +intervening call to operator delete(void*) (17.4.3.7). For such a +non-null value of ptr, reclaims storage allocated by the earlier +call to the default operator new. +
++-14- Remarks: It is unspecified under what conditions part or all of +such reclaimed storage is allocated by a subsequent call to operator +new or any of calloc, malloc, or realloc, +declared in <cstdlib>. +
+void operator delete(void* ptr, const std::nothrow_t&) throw(); ++ +++ ++-15- Effects: Same as above, except that it is called by the +implementation when an exception propagates from a nothrow placement version +of the new-expression (i.e. when the constructor throws an exception). +
++-16- Replaceable: a C++ program may define a function with this function +signature that displaces the default version defined by the C++ Standard +library. +
++-17- Requires: the value of ptr is null or the +value returned by an earlier call to the (possibly replaced) operator +new(std::size_t) or operator new(std::size_t, const +std::nothrow_t&).
++-18- Default behavior: Calls operator delete(ptr). +
+
+Change 18.5.1.2 [new.delete.array] +
+ +++ + + +void* operator new[](std::size_t size, const std::nothrow_t&) throw(); ++ +++ ++-5- Effects: Same as above, except that it is called by a placement +version of a new-expression when a C++ program prefers a null pointer result as +an error indication, instead of a bad_alloc exception. +
+ ++-6- Replaceable: a C++ program can define a function with this function +signature that displaces the default version defined by the C++ Standard +library. +
+ ++-7- Required behavior:
+ +Same as for operator new(std::size_t, +const std::nothrow_t&). This nothrow version of operator new[] +returns a pointer obtained as if acquired from the ordinary version.+Return a non-null pointer to suitably aligned storage (3.7.4), or else +return a null pointer. This nothrow version of operator new returns a pointer +obtained as if acquired from the (possibly replaced) operator +new[](std::size_t size). This requirement is binding on a +replacement version of this function. ++-8- Default behavior:
+ +Returns operator new(size, +nothrow).++
+- +Calls operator new[](size). +
+- +If the call to operator new[](size) returns normally, returns +the result of that call, else +
+- +if the call to operator new[](size) throws an exception, returns +a null pointer. +
+void operator delete[](void* ptr) throw(); +void operator delete[](void* ptr, const std::nothrow_t&) throw(); ++ +++ ++-9- Effects: The deallocation function (3.7.4.2) called by the +array form of a delete-expression to render the value of +ptr invalid. +
+ ++-10- Replaceable: a C++ program can define a function with this function +signature that displaces the default version defined by the C++ Standard +library. +
+ ++-11- Requires: the value of +ptr is null or the value returned by an earlier call to +operator new[](std::size_t) or operator new[](std::size_t, const +std::nothrow_t&). +
+ ++-12- Default behavior: Calls operator delete(ptr) or +operator delete[](ptr
+, std::nothrow) respectively. +
Rationale:
+Yes, they may become unlinked, and that is by design. If a user +replaces one, the user should also replace the other.
+ +[ +Reopened due to a gcc conversation between Howard, Martin and Gaby. Forwarding +or not is visible behavior to the client and it would be useful for the client +to know which behavior it could depend on. +]
+ + +[ +Batavia: Robert voiced serious reservations about backwards compatibility for +his customers. +]
+ + + + + + +Section: 24.1 [iterator.requirements] Status: TC + Submitter: Stephen Cleary Date: 2000-02-02
+View other active issues in [iterator.requirements].
+View all other issues in [iterator.requirements].
+View all issues with TC status.
+Discussion:
+In 24.1 paragraph 5, it is stated ". . . Dereferenceable and +past-the-end values are always non-singular."
+This places an unnecessary restriction on past-the-end iterators for +containers with forward iterators (for example, a singly-linked list). If the +past-the-end value on such a container was a well-known singular value, it would +still satisfy all forward iterator requirements.
+Removing this restriction would allow, for example, a singly-linked list +without a "footer" node.
+This would have an impact on existing code that expects past-the-end +iterators obtained from different (generic) containers being not equal.
+ + +Proposed resolution:
+Change 24.1 [iterator.requirements] paragraph 5, the last sentence, from:
+++Dereferenceable and past-the-end values are always non-singular.
+
to:
+++ + +Dereferenceable values are always non-singular.
+
Rationale:
+For some kinds of containers, including singly linked lists and +zero-length vectors, null pointers are perfectly reasonable past-the-end +iterators. Null pointers are singular. +
+ + + + +Section: 21.3 [basic.string] Status: TC + Submitter: Igor Stauder Date: 2000-02-11
+View other active issues in [basic.string].
+View all other issues in [basic.string].
+View all issues with TC status.
+Discussion:
+In Section 21.3 [basic.string] the basic_string member function +declarations use a consistent style except for the following functions:
+++void push_back(const charT); +basic_string& assign(const basic_string&); +void swap(basic_string<charT,traits,Allocator>&);+
- push_back, assign, swap: missing argument name
+- push_back: use of const with charT (i.e. POD type passed by value
+not by reference - should be charT or const charT& )
+- swap: redundant use of template parameters in argument
+basic_string<charT,traits,Allocator>&
Proposed resolution:
+In Section 21.3 [basic.string] change the basic_string member +function declarations push_back, assign, and swap to:
+++ + +void push_back(charT c); + +basic_string& assign(const basic_string& str); +void swap(basic_string& str);+
Rationale:
+Although the standard is in general not consistent in declaration +style, the basic_string declarations are consistent other than the +above. The LWG felt that this was sufficient reason to merit the +change. +
+ + + + +Section: 25 [algorithms] Status: TC + Submitter: Lisa Lippincott Date: 2000-02-15
+View all other issues in [algorithms].
+View all issues with TC status.
+Discussion:
+In paragraph 9 of section 25 [algorithms], it is written:
+++ + +In the description of the algorithms operators + and - are used + for some of the iterator categories for which they do not have to + be defined. In these cases the semantics of [...] a-b is the same + as of
+
+
+ return distance(a, b);
Proposed resolution:
+On the last line of paragraph 9 of section 25 [algorithms] change +"a-b" to "b-a".
+ + +Rationale:
+There are two ways to fix the defect; change the description to b-a +or change the return to distance(b,a). The LWG preferred the +former for consistency.
+ + + + +Section: 21.3.8.9 [string.io] Status: TC + Submitter: Scott Snyder Date: 2000-02-04
+View all other issues in [string.io].
+View all issues with TC status.
+Discussion:
+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 +stream.
+This implies that the typical construction
+++std::istream is; +std::string str; +... +while (is >> str) ... ;+
(which tests failbit) is not required to terminate at EOF.
+Furthermore, this is inconsistent with other extraction operators, +which do include this requirement. (See sections 27.6.1.2 [istream.formatted] and 27.6.1.3 [istream.unformatted]), where this +requirement is present, either explicitly or implicitly, for the +extraction operators. It is also present explicitly in the description +of getline (istream&, string&, charT) in section 21.3.8.9 [string.io] paragraph 8.)
+ + +Proposed resolution:
+Insert new paragraph after paragraph 2 in section 21.3.8.9 [string.io]:
++ ++ + + + +If the function extracts no characters, it calls +is.setstate(ios::failbit) which may throw ios_base::failure +(27.4.4.3).
+
Section: 25.3.7 [alg.min.max] Status: TC + Submitter: Nico Josuttis Date: 2000-02-26
+View all other issues in [alg.min.max].
+View all issues with TC status.
+Discussion:
+The standard doesn't specify what min_element() and max_element() shall +return if the range is empty (first equals last). The usual implementations +return last. This problem seems also apply to partition(), stable_partition(), +next_permutation(), and prev_permutation().
+ + +Proposed resolution:
+In 25.3.7 [alg.min.max] - Minimum and maximum, paragraphs 7 and +9, append: Returns last if first==last.
+ + +Rationale:
+The LWG looked in some detail at all of the above mentioned +algorithms, but believes that except for min_element() and +max_element() it is already clear that last is returned if first == +last.
+ + + + +Section: 23.3.3 [set], 23.3.4 [multiset] Status: WP + Submitter: Judy Ward Date: 2000-02-28
+View all other issues in [set].
+View all issues with WP status.
+Duplicate of: 450
+Discussion:
+The specification for the associative container requirements in +Table 69 state that the find member function should "return +iterator; const_iterator for constant a". The map and multimap +container descriptions have two overloaded versions of find, but set +and multiset do not, all they have is:
+++ + +iterator find(const key_type & x) const;+
Proposed resolution:
+Change the prototypes for find(), lower_bound(), upper_bound(), and +equal_range() in section 23.3.3 [set] and section 23.3.4 [multiset] to each have two overloads:
+++ +iterator find(const key_type & x); +const_iterator find(const key_type & x) const;+iterator lower_bound(const key_type & x); +const_iterator lower_bound(const key_type & x) const;+iterator upper_bound(const key_type & x); +const_iterator upper_bound(const key_type & x) const;+pair<iterator, iterator> equal_range(const key_type & x); +pair<const_iterator, const_iterator> equal_range(const key_type & x) const;+
[Tokyo: At the request of the LWG, Judy Ward provided wording +extending the proposed resolution to lower_bound, upper_bound, and +equal_range.]
+ + + + + + +Section: 22.2.8 [facets.examples] Status: TC + Submitter: Martin Sebor Date: 2000-02-29
+View all other issues in [facets.examples].
+View all issues with TC status.
+Discussion:
+The example in 22.2.8, paragraph 11 contains the following errors:
+1) The member function `My::JCtype::is_kanji()' is non-const; the function +must be const in order for it to be callable on a const object (a reference to +which which is what std::use_facet<>() returns).
+2) In file filt.C, the definition of `JCtype::id' must be qualified with the +name of the namespace `My'.
+3) In the definition of `loc' and subsequently in the call to use_facet<>() +in main(), the name of the facet is misspelled: it should read `My::JCtype' +rather than `My::JCType'.
+ + +Proposed resolution:
+Replace the "Classifying Japanese characters" example in 22.2.8, +paragraph 11 with the following:
+#include <locale>+
namespace My { + using namespace std; + class JCtype : public locale::facet { + public: + static locale::id id; // required for use as a new locale facet + bool is_kanji (wchar_t c) const; + JCtype() {} + protected: + ~JCtype() {} + }; +}+
// file: filt.C +#include <iostream> +#include <locale> +#include "jctype" // above +std::locale::id My::JCtype::id; // the static JCtype member +declared above.+
int main() +{ + using namespace std; + typedef ctype<wchar_t> wctype; + locale loc(locale(""), // the user's preferred locale... + new My::JCtype); // and a new feature ... + wchar_t c = use_facet<wctype>(loc).widen('!'); + if (!use_facet<My::JCtype>(loc).is_kanji(c)) + cout << "no it isn't!" << endl; + return 0; +}+ + + + +
Section: 27.4.2.7 [ios.base.cons] Status: TC + Submitter: Jonathan Schilling, Howard Hinnant Date: 2000-03-13
+View all issues with TC status.
+Discussion:
+The pre-conditions for the ios_base destructor are described in 27.4.2.7 +paragraph 2:
+++Effects: Destroys an object of class ios_base. Calls each registered + callback pair (fn,index) (27.4.2.6) as (*fn)(erase_event,*this,index) at such + time that any ios_base member function called from within fn has well defined + results.
+
But what is not clear is: If no callback functions were ever registered, does +it matter whether the ios_base members were ever initialized?
+For instance, does this program have defined behavior:
+++#include <ios>+class D : public std::ios_base { };+int main() { D d; }+
It seems that registration of a callback function would surely affect the +state of an ios_base. That is, when you register a callback function with an +ios_base, the ios_base must record that fact somehow.
+But if after construction the ios_base is in an indeterminate state, and that +state is not made determinate before the destructor is called, then how would +the destructor know if any callbacks had indeed been registered? And if the +number of callbacks that had been registered is indeterminate, then is not the +behavior of the destructor undefined?
+By comparison, the basic_ios class description in 27.4.4.1 paragraph 2 makes +it explicit that destruction before initialization results in undefined +behavior.
+ + +Proposed resolution:
+Modify 27.4.2.7 paragraph 1 from
+++Effects: Each ios_base member has an indeterminate value after + construction.
+
to
+++ + + + +Effects: Each ios_base member has an indeterminate +value after construction. These members must be initialized by calling +basic_ios::init. If an ios_base object is destroyed before these +initializations have taken place, the behavior is undefined.
+
Section: 22.2.2.1.2 [facet.num.get.virtuals] Status: WP + Submitter: Matt Austern Date: 2000-03-14
+View other active issues in [facet.num.get.virtuals].
+View all other issues in [facet.num.get.virtuals].
+View all issues with WP status.
+Discussion:
+Stage 2 processing of numeric conversion is broken.
+ +Table 55 in 22.2.2.1.2 says that when basefield is 0 the integral +conversion specifier is %i. A %i specifier determines a number's base +by its prefix (0 for octal, 0x for hex), so the intention is clearly +that a 0x prefix is allowed. Paragraph 8 in the same section, +however, describes very precisely how characters are processed. (It +must be done "as if" by a specified code fragment.) That +description does not allow a 0x prefix to be recognized.
+ +Very roughly, stage 2 processing reads a char_type ct. It converts +ct to a char, not by using narrow but by looking it up in a +translation table that was created by widening the string literal +"0123456789abcdefABCDEF+-". The character "x" is +not found in that table, so it can't be recognized by stage 2 +processing.
+ + +Proposed resolution:
+In 22.2.2.1.2 paragraph 8, replace the line:
+++static const char src[] = "0123456789abcdefABCDEF+-";+
with the line:
+++ + +static const char src[] = "0123456789abcdefxABCDEFX+-";+
Rationale:
+If we're using the technique of widening a string literal, the +string literal must contain every character we wish to recognize. +This technique has the consequence that alternate representations +of digits will not be recognized. This design decision was made +deliberately, with full knowledge of that limitation.
+ + + + + +Section: 17.3.1.3 [structure.specifications] Status: TC + Submitter: Judy Ward Date: 2000-03-17
+View all other issues in [structure.specifications].
+View all issues with TC status.
+Discussion:
+Section 21.3.6.8 describes the basic_string::compare function this way:
+++21.3.6.8 - basic_string::compare [lib.string::compare] + +int compare(size_type pos1, size_type n1, + const basic_string<charT,traits,Allocator>& str , + size_type pos2 , size_type n2 ) const; + +-4- Returns: + + basic_string<charT,traits,Allocator>(*this,pos1,n1).compare( + basic_string<charT,traits,Allocator>(str,pos2,n2)) .+
and the constructor that's implicitly called by the above is +defined to throw an out-of-range exception if pos > str.size(). See +section 21.3.1 [string.require] paragraph 4.
+ +On the other hand, the compare function descriptions themselves don't have +"Throws: " clauses and according to 17.3.1.3, paragraph 3, elements +that do not apply to a function are omitted.
+So it seems there is an inconsistency in the standard -- are the +"Effects" clauses correct, or are the "Throws" clauses +missing?
+ + +Proposed resolution:
+In 17.3.1.3 [structure.specifications] paragraph 3, the footnote 148 attached to +the sentence "Descriptions of function semantics contain the +following elements (as appropriate):", insert the word +"further" so that the foot note reads:
+++ + +To save space, items that do not apply to a function are + omitted. For example, if a function does not specify any further + preconditions, there will be no "Requires" paragraph.
+
Rationale:
+The standard is somewhat inconsistent, but a failure to note a +throw condition in a throws clause does not grant permission not to +throw. The inconsistent wording is in a footnote, and thus +non-normative. The proposed resolution from the LWG clarifies the +footnote.
+ + + + +Section: 25.2.10 [alg.reverse] Status: TC + Submitter: Dave Abrahams Date: 2000-03-21
+View all issues with TC status.
+Discussion:
+Shouldn't the effects say "applies iter_swap to all pairs..."?
+ + +Proposed resolution:
+In 25.2.10 [alg.reverse], replace:
+++ Effects: For each non-negative integer i <= (last - first)/2, + applies swap to all pairs of iterators first + i, (last - i) - 1. +
with:
++ + + + ++ Effects: For each non-negative integer i <= (last - first)/2, + applies iter_swap to all pairs of iterators first + i, (last - i) - 1. +
Section: 23.1.4 [associative.reqmts] Status: TC + Submitter: Ed Brey Date: 2000-03-23
+View all other issues in [associative.reqmts].
+View all issues with TC status.
+Discussion:
+In the associative container requirements table in 23.1.2 paragraph 7, +a.clear() has complexity "log(size()) + N". However, the meaning of N +is not defined.
+ + +Proposed resolution:
+In the associative container requirements table in 23.1.2 paragraph +7, the complexity of a.clear(), change "log(size()) + N" to +"linear in size()".
+ + +Rationale:
+It's the "log(size())", not the "N", that is in +error: there's no difference between O(N) and O(N + +log(N)). The text in the standard is probably an incorrect +cut-and-paste from the range version of erase.
+ + + + +Section: 17.4.4.3 [global.functions] Status: WP + Submitter: Dave Abrahams Date: 2000-04-01
+View all other issues in [global.functions].
+View all issues with WP status.
+Discussion:
+Are algorithms in std:: allowed to use other algorithms without qualification, so functions in +user namespaces might be found through Koenig lookup?
+For example, a popular standard library implementation includes this +implementation of std::unique:
+++namespace std { + template <class _ForwardIter> + _ForwardIter unique(_ForwardIter __first, _ForwardIter __last) { + __first = adjacent_find(__first, __last); + return unique_copy(__first, __last, __first); + } + }+
Imagine two users on opposite sides of town, each using unique on his own +sequences bounded by my_iterators . User1 looks at his standard library +implementation and says, "I know how to implement a more efficient +unique_copy for my_iterators", and writes:
+++namespace user1 { + class my_iterator; + // faster version for my_iterator + my_iterator unique_copy(my_iterator, my_iterator, my_iterator); + }+
user1::unique_copy() is selected by Koenig lookup, as he intended.
+User2 has other needs, and writes:
+++namespace user2 { + class my_iterator; + // Returns true iff *c is a unique copy of *a and *b. + bool unique_copy(my_iterator a, my_iterator b, my_iterator c); + }+
User2 is shocked to find later that his fully-qualified use of +std::unique(user2::my_iterator, user2::my_iterator, user2::my_iterator) fails to +compile (if he's lucky). Looking in the standard, he sees the following Effects +clause for unique():
+++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
+
The standard gives user2 absolutely no reason to think he can interfere with +std::unique by defining names in namespace user2. His standard library has been +built with the template export feature, so he is unable to inspect the +implementation. User1 eventually compiles his code with another compiler, and +his version of unique_copy silently stops being called. Eventually, he realizes +that he was depending on an implementation detail of his library and had no +right to expect his unique_copy() to be called portably.
+On the face of it, and given above scenario, it may seem obvious that the +implementation of unique() shown is non-conforming because it uses unique_copy() +rather than ::std::unique_copy(). Most standard library implementations, +however, seem to disagree with this notion.
+[Tokyo: Steve Adamczyk from +the core working group indicates that "std::" is sufficient; +leading "::" qualification is not required because any namespace +qualification is sufficient to suppress Koenig lookup.]
+ + +Proposed resolution:
+Add a paragraph and a note at the end of +17.4.4.3 [global.functions]:
++ ++ +Unless otherwise specified, no global or non-member function in the +standard library shall use a function from another namespace which is +found through argument-dependent name lookup (3.4.2 [basic.lookup.argdep]).
+ +[Note: the phrase "unless otherwise specified" is intended to +allow Koenig lookup in cases like that of ostream_iterators:
+
+ +
+ Effects:++*out_stream << value;
+
+ if(delim != 0) *out_stream << delim;
+ return (*this);--end note]
+
[Tokyo: The LWG agrees that this is a defect in the standard, but +is as yet unsure if the proposed resolution is the best +solution. Furthermore, the LWG believes that the same problem of +unqualified library names applies to wording in the standard itself, +and has opened issue 229 accordingly. Any resolution of +issue 225 should be coordinated with the resolution of +issue 229.]
+ + +[Toronto: The LWG is not sure if this is a defect in the +standard. Most LWG members believe that an implementation of +std::unique like the one quoted in this issue is already +illegal, since, under certain circumstances, its semantics are not +those specified in the standard. The standard's description of +unique does not say that overloading adjacent_find +should have any effect.]
+ + +[Curaçao: An LWG-subgroup spent an afternoon working on issues +225, 226, and 229. Their conclusion was that the issues should be +separated into an LWG portion (Howard's paper, N1387=02-0045), and a +EWG portion (Dave will write a proposal). The LWG and EWG had +(separate) discussions of this plan the next day. The proposed +resolution for this issue is in accordance with Howard's paper.]
+ + + + +Rationale:
+It could be argued that this proposed isn't strictly necessary, + that the Standard doesn't grant implementors license to write a + standard function that behaves differently than specified in the + Standard just because of an unrelated user-defined name in some + other namespace. However, this is at worst a clarification. It is + surely right that algorithsm shouldn't pick up random names, that + user-defined names should have no effect unless otherwise specified. + Issue 226 deals with the question of when it is + appropriate for the standard to explicitly specify otherwise.
+ + + + + +Section: 17.4.3.2 [reserved.names] Status: WP + Submitter: Dave Abrahams Date: 2000-04-01
+View all other issues in [reserved.names].
+View all issues with WP status.
+Discussion:
+The issues are:
+1. How can a 3rd party library implementor (lib1) write a version of a standard +algorithm which is specialized to work with his own class template?
+2. How can another library implementor (lib2) write a generic algorithm which +will take advantage of the specialized algorithm in lib1?
+This appears to be the only viable answer under current language rules:
+++namespace lib1 +{ + // arbitrary-precision numbers using T as a basic unit + template <class T> + class big_num { //... + }; ++// defining this in namespace std is illegal (it would be an + // overload), so we hope users will rely on Koenig lookup + template <class T> + void swap(big_int<T>&, big_int<T>&); +}+#include <algorithm> +namespace lib2 +{ + template <class T> + void generic_sort(T* start, T* end) + { + ... + // using-declaration required so we can work on built-in types + using std::swap; + // use Koenig lookup to find specialized algorithm if available + swap(*x, *y); + } +}+
This answer has some drawbacks. First of all, it makes writing lib2 difficult +and somewhat slippery. The implementor needs to remember to write the +using-declaration, or generic_sort will fail to compile when T is a built-in +type. The second drawback is that the use of this style in lib2 effectively +"reserves" names in any namespace which defines types which may +eventually be used with lib2. This may seem innocuous at first when applied to +names like swap, but consider more ambiguous names like unique_copy() instead. +It is easy to imagine the user wanting to define these names differently in his +own namespace. A definition with semantics incompatible with the standard +library could cause serious problems (see issue 225).
+Why, you may ask, can't we just partially specialize std::swap()? It's +because the language doesn't allow for partial specialization of function +templates. If you write:
+++namespace std +{ + template <class T> + void swap(lib1::big_int<T>&, lib1::big_int<T>&); +}+
You have just overloaded std::swap, which is illegal under the current +language rules. On the other hand, the following full specialization is legal:
+++ +namespace std +{ + template <> + void swap(lib1::other_type&, lib1::other_type&); +}+
This issue reflects concerns raised by the "Namespace issue +with specialized swap" thread on comp.lang.c++.moderated. A +similar set of concerns was earlier raised on the boost.org mailing +list and the ACCU-general mailing list. Also see library reflector +message c++std-lib-7354.
+ ++J. C. van Winkel points out (in c++std-lib-9565) another unexpected +fact: it's impossible to output a container of std::pair's using copy +and an ostream_iterator, as long as both pair-members are built-in or +std:: types. That's because a user-defined operator<< for (for +example) std::pair<const std::string, int> will not be found: +lookup for operator<< will be performed only in namespace std. +Opinions differed on whether or not this was a defect, and, if so, +whether the defect is that something is wrong with user-defined +functionality and std, or whether it's that the standard library does +not provide an operator<< for std::pair<>. +
+ + + +Proposed resolution:
+ +Adopt the wording proposed in Howard Hinnant's paper + N1523=03-0106, "Proposed Resolution To LWG issues 225, 226, 229".
+ + +[Tokyo: Summary, "There is no conforming way to extend +std::swap for user defined templates." The LWG agrees that +there is a problem. Would like more information before +proceeding. This may be a core issue. Core issue 229 has been opened +to discuss the core aspects of this problem. It was also noted that +submissions regarding this issue have been received from several +sources, but too late to be integrated into the issues list. +]
+ + +[Post-Tokyo: A paper with several proposed resolutions, +J16/00-0029==WG21/N1252, "Shades of namespace std functions +" by Alan Griffiths, is in the Post-Tokyo mailing. It +should be considered a part of this issue.]
+ + +[Toronto: Dave Abrahams and Peter Dimov have proposed a +resolution that involves core changes: it would add partial +specialization of function template. The Core Working Group is +reluctant to add partial specialization of function templates. It is +viewed as a large change, CWG believes that proposal presented leaves +some syntactic issues unanswered; if the CWG does add partial +specialization of function templates, it wishes to develop its own +proposal. The LWG continues to believe that there is a serious +problem: there is no good way for users to force the library to use +user specializations of generic standard library functions, and in +certain cases (e.g. transcendental functions called by +valarray and complex) this is important. Koenig +lookup isn't adequate, since names within the library must be +qualified with std (see issue 225), specialization doesn't +work (we don't have partial specialization of function templates), and +users aren't permitted to add overloads within namespace std. +]
+ + +[Copenhagen: Discussed at length, with no consensus. Relevant +papers in the pre-Copenhagen mailing: N1289, N1295, N1296. Discussion +focused on four options. (1) Relax restrictions on overloads within +namespace std. (2) Mandate that the standard library use unqualified +calls for swap and possibly other functions. (3) Introduce +helper class templates for swap and possibly other functions. +(4) Introduce partial specialization of function templates. Every +option had both support and opposition. Straw poll (first number is +support, second is strongly opposed): (1) 6, 4; (2) 6, 7; (3) 3, 8; +(4) 4, 4.]
+ + +[Redmond: Discussed, again no consensus. Herb presented an +argument that a user who is defining a type T with an +associated swap should not be expected to put that +swap in namespace std, either by overloading or by partial +specialization. The argument is that swap is part of +T's interface, and thus should to in the same namespace as +T and only in that namespace. If we accept this argument, +the consequence is that standard library functions should use +unqualified call of swap. (And which other functions? Any?) +A small group (Nathan, Howard, Jeremy, Dave, Matt, Walter, Marc) will +try to put together a proposal before the next meeting.]
+ + +[Curaçao: An LWG-subgroup spent an afternoon working on issues +225, 226, and 229. Their conclusion was that the issues should be +separated into an LWG portion (Howard's paper, N1387=02-0045), and a +EWG portion (Dave will write a proposal). The LWG and EWG had +(separate) discussions of this plan the next day. The proposed +resolution is the one proposed by Howard.]
+ + +[Santa Cruz: the LWG agreed with the general direction of + Howard's paper, N1387. (Roughly: Koenig lookup is disabled unless + we say otherwise; this issue is about when we do say otherwise.) + However, there were concerns about wording. Howard will provide new + wording. Bill and Jeremy will review it.]
+ + +[Kona: Howard proposed the new wording. The LWG accepted his + proposed resolution.]
+ + + + +Rationale:
+Informally: introduce a Swappable concept, and specify that the + value types of the iterators passed to certain standard algorithms + (such as iter_swap, swap_ranges, reverse, rotate, and sort) conform + to that concept. The Swappable concept will make it clear that + these algorithms use unqualified lookup for the calls + to swap. Also, in 26.5.3.3 [valarray.transcend] paragraph 1, + state that the valarray transcendentals use unqualified lookup.
+ + + + + +Section: 25.2.3 [alg.swap] Status: TC + Submitter: Dave Abrahams Date: 2000-04-09
+View all other issues in [alg.swap].
+View all issues with TC status.
+Discussion:
+25.2.2 reads:
+++template<class T> void swap(T& a, T& b);
+
+
+ Requires: Type T is Assignable (_lib.container.requirements_).
+ Effects: Exchanges values stored in two locations.
The only reasonable** generic implementation of swap requires construction of a + new temporary copy of one of its arguments:
+++template<class T> void swap(T& a, T& b); + { + T tmp(a); + a = b; + b = tmp; + }+
But a type which is only Assignable cannot be swapped by this implementation.
+**Yes, there's also an unreasonable implementation which would require T to be + DefaultConstructible instead of CopyConstructible. I don't think this is worthy + of consideration:
+++ + +template<class T> void swap(T& a, T& b); +{ + T tmp; + tmp = a; + a = b; + b = tmp; +}+
Proposed resolution:
+Change 25.2.2 paragraph 1 from:
+++Requires: Type T is Assignable (23.1).
+
to:
+++ + + + + +Requires: Type T is CopyConstructible (20.1.3) and Assignable (23.1)
+
Section: 22.2 [locale.categories] Status: WP + Submitter: Dietmar Kühl Date: 2000-04-20
+View other active issues in [locale.categories].
+View all other issues in [locale.categories].
+View all issues with WP status.
+Discussion:
+The sections 22.2.1.2 [locale.ctype.byname], 22.2.1.5 +[locale.codecvt.byname], +sref ref="22.2.1.6", 22.2.3.2 [locale.numpunct.byname], 22.2.4.2 +[locale.collate.byname], 22.2.5.4 [locale.time.put.byname], 22.2.6.4 +[locale.moneypunct.byname], and 22.2.7.2 [locale.messages.byname] +overspecify the +definitions of the "..._byname" classes by listing a bunch +of virtual functions. At the same time, no semantics of these +functions are defined. Real implementations do not define these +functions because the functional part of the facets is actually +implemented in the corresponding base classes and the constructor of +the "..._byname" version just provides suitable date used by +these implementations. For example, the 'numpunct' methods just return +values from a struct. The base class uses a statically initialized +struct while the derived version reads the contents of this struct +from a table. However, no virtual function is defined in +'numpunct_byname'.
+ +For most classes this does not impose a problem but specifically +for 'ctype' it does: The specialization for 'ctype_byname<char>' +is required because otherwise the semantics would change due to the +virtual functions defined in the general version for 'ctype_byname': +In 'ctype<char>' the method 'do_is()' is not virtual but it is +made virtual in both 'ctype<cT>' and 'ctype_byname<cT>'. +Thus, a class derived from 'ctype_byname<char>' can tell whether +this class is specialized or not under the current specification: +Without the specialization, 'do_is()' is virtual while with +specialization it is not virtual.
+ + +Proposed resolution:
+Change section 22.2.1.2 (lib.locale.ctype.byname) to become:
+namespace std { + template <class charT> + class ctype_byname : public ctype<charT> { + public: + typedef ctype<charT>::mask mask; + explicit ctype_byname(const char*, size_t refs = 0); + protected: + ~ctype_byname(); // virtual + }; + }+
Change section 22.2.1.6 (lib.locale.codecvt.byname) to become:
+namespace std { + template <class internT, class externT, class stateT> + class codecvt_byname : public codecvt<internT, externT, stateT> { + public: + explicit codecvt_byname(const char*, size_t refs = 0); + protected: + ~codecvt_byname(); // virtual + }; + } ++
Change section 22.2.3.2 (lib.locale.numpunct.byname) to become:
+namespace std { + template <class charT> + class numpunct_byname : public numpunct<charT> { + // this class is specialized for char and wchar_t. + public: + typedef charT char_type; + typedef basic_string<charT> string_type; + explicit numpunct_byname(const char*, size_t refs = 0); + protected: + ~numpunct_byname(); // virtual + }; + }+
Change section 22.2.4.2 (lib.locale.collate.byname) to become:
+namespace std { + template <class charT> + class collate_byname : public collate<charT> { + public: + typedef basic_string<charT> string_type; + explicit collate_byname(const char*, size_t refs = 0); + protected: + ~collate_byname(); // virtual + }; + }+
Change section 22.2.5.2 (lib.locale.time.get.byname) to become:
+namespace std { + template <class charT, class InputIterator = istreambuf_iterator<charT> > + class time_get_byname : public time_get<charT, InputIterator> { + public: + typedef time_base::dateorder dateorder; + typedef InputIterator iter_type+
explicit time_get_byname(const char*, size_t refs = 0); + protected: + ~time_get_byname(); // virtual + }; + }+
Change section 22.2.5.4 (lib.locale.time.put.byname) to become:
+namespace std { + template <class charT, class OutputIterator = ostreambuf_iterator<charT> > + class time_put_byname : public time_put<charT, OutputIterator> + { + public: + typedef charT char_type; + typedef OutputIterator iter_type;+
explicit time_put_byname(const char*, size_t refs = 0); + protected: + ~time_put_byname(); // virtual + }; + }"+
Change section 22.2.6.4 (lib.locale.moneypunct.byname) to become:
+namespace std { + template <class charT, bool Intl = false> + class moneypunct_byname : public moneypunct<charT, Intl> { + public: + typedef money_base::pattern pattern; + typedef basic_string<charT> string_type;+
explicit moneypunct_byname(const char*, size_t refs = 0); + protected: + ~moneypunct_byname(); // virtual + }; + }+
Change section 22.2.7.2 (lib.locale.messages.byname) to become:
+namespace std { + template <class charT> + class messages_byname : public messages<charT> { + public: + typedef messages_base::catalog catalog; + typedef basic_string<charT> string_type;+
explicit messages_byname(const char*, size_t refs = 0); + protected: + ~messages_byname(); // virtual + }; + }+
Remove section 22.2.1.4 [locale.codecvt] completely (because in +this case only those members are defined to be virtual which are +defined to be virtual in 'ctype<cT>'.)
+ +[Post-Tokyo: Dietmar Kühl submitted this issue at the request of +the LWG to solve the underlying problems raised by issue 138.]
+ + +[Copenhagen: proposed resolution was revised slightly, to remove +three last virtual functions from messages_byname.]
+ + + + + + + +Section: 17.4.1.1 [contents] Status: WP + Submitter: Steve Clamage Date: 2000-04-19
+View all issues with WP status.
+Discussion:
+Throughout the library chapters, the descriptions of library entities refer +to other library entities without necessarily qualifying the names.
+ +For example, section 25.2.2 "Swap" describes the effect of +swap_ranges in terms of the unqualified name "swap". This section +could reasonably be interpreted to mean that the library must be implemented so +as to do a lookup of the unqualified name "swap", allowing users to +override any ::std::swap function when Koenig lookup applies.
+ +Although it would have been best to use explicit qualification with +"::std::" throughout, too many lines in the standard would have to be +adjusted to make that change in a Technical Corrigendum.
+ +Issue 182, which addresses qualification of +size_t, is a special case of this. +
+ + +Proposed resolution:
+To section 17.4.1.1 "Library contents" Add the following paragraph:
+++ +Whenever a name x defined in the standard library is mentioned, the name x + is assumed to be fully qualified as ::std::x, unless explicitly described + otherwise. For example, if the Effects section for library function F is + described as calling library function G, the function ::std::G is meant.
+
[Post-Tokyo: Steve Clamage submitted this issue at the request of +the LWG to solve a problem in the standard itself similar to the +problem within implementations of library identified by issue 225. Any resolution of issue 225 should be +coordinated with the resolution of this issue.]
+ + +[post-Toronto: Howard is undecided about whether it is +appropriate for all standard library function names referred to in +other standard library functions to be explicitly qualified by +std: it is common advice that users should define global +functions that operate on their class in the same namespace as the +class, and this requires argument-dependent lookup if those functions +are intended to be called by library code. Several LWG members are +concerned that valarray appears to require argument-dependent lookup, +but that the wording may not be clear enough to fall under +"unless explicitly described otherwise".]
+ + +[Curaçao: An LWG-subgroup spent an afternoon working on issues +225, 226, and 229. Their conclusion was that the issues should be +separated into an LWG portion (Howard's paper, N1387=02-0045), and a +EWG portion (Dave will write a proposal). The LWG and EWG had +(separate) discussions of this plan the next day. This paper resolves +issues 225 and 226. In light of that resolution, the proposed +resolution for the current issue makes sense.]
+ + + + + + + +Section: 17 [library] Status: WP + Submitter: Beman Dawes Date: 2000-04-26
+View all other issues in [library].
+View all issues with WP status.
+Discussion:
+Issue 227 identified an instance (std::swap) where +Assignable was specified without also specifying +CopyConstructible. The LWG asked that the standard be searched to +determine if the same defect existed elsewhere.
+ +There are a number of places (see proposed resolution below) where +Assignable is specified without also specifying +CopyConstructible. There are also several cases where both are +specified. For example, 26.4.1 [rand.req].
+ + +Proposed resolution:
+In 23.1 [container.requirements] table 65 for value_type: +change "T is Assignable" to "T is CopyConstructible and +Assignable" +
+ +In 23.1.4 [associative.reqmts] table 69 X::key_type; change
+"Key is Assignable" to "Key is
+CopyConstructible and Assignable"
+
In 24.1.2 [output.iterators] paragraph 1, change: +
+++A class or a built-in type X satisfies the requirements of an +output iterator if X is an Assignable type (23.1) and also the +following expressions are valid, as shown in Table 73: +
+
to: +
+++ +A class or a built-in type X satisfies the requirements of an +output iterator if X is a CopyConstructible (20.1.3) and Assignable +type (23.1) and also the following expressions are valid, as shown in +Table 73: +
+
[Post-Tokyo: Beman Dawes submitted this issue at the request of +the LWG. He asks that the 25.2.5 [alg.replace] and 25.2.6 [alg.fill] changes be studied carefully, as it is not clear that +CopyConstructible is really a requirement and may be +overspecification.]
+ + +[Portions of the resolution for issue 230 have been superceded by +the resolution of issue 276.]
+ + + + +Rationale:
+The original proposed resolution also included changes to input +iterator, fill, and replace. The LWG believes that those changes are +not necessary. The LWG considered some blanket statement, where an +Assignable type was also required to be Copy Constructible, but +decided against this because fill and replace really don't require the +Copy Constructible property.
+ + + + +Section: 22.2.2.2.2 [facet.num.put.virtuals] Status: WP + Submitter: James Kanze, Stephen Clamage Date: 2000-04-25
+View all other issues in [facet.num.put.virtuals].
+View all issues with WP status.
+Discussion:
+What is the following program supposed to output?
+#include <iostream> + + int + main() + { + std::cout.setf( std::ios::scientific , std::ios::floatfield ) ; + std::cout.precision( 0 ) ; + std::cout << 1.00 << '\n' ; + return 0 ; + }+
From my C experience, I would expect "1e+00"; this is what +printf("%.0e" , 1.00 ); does. G++ outputs +"1.000000e+00".
+ +The only indication I can find in the standard is 22.2.2.2.2/11, +where it says "For conversion from a floating-point type, if +(flags & fixed) != 0 or if str.precision() > 0, then +str.precision() is specified in the conversion specification." +This is an obvious error, however, fixed is not a mask for a field, +but a value that a multi-bit field may take -- the results of and'ing +fmtflags with ios::fixed are not defined, at least not if +ios::scientific has been set. G++'s behavior corresponds to what might +happen if you do use (flags & fixed) != 0 with a typical +implementation (floatfield == 3 << something, fixed == 1 +<< something, and scientific == 2 << something).
+ +Presumably, the intent is either (flags & floatfield) != 0, or +(flags & floatfield) == fixed; the first gives something more or +less like the effect of precision in a printf floating point +conversion. Only more or less, of course. In order to implement printf +formatting correctly, you must know whether the precision was +explicitly set or not. Say by initializing it to -1, instead of 6, and +stating that for floating point conversions, if precision < -1, 6 +will be used, for fixed point, if precision < -1, 1 will be used, +etc. Plus, of course, if precision == 0 and flags & floatfield == +0, 1 should be = used. But it probably isn't necessary to emulate all +of the anomalies of printf:-).
+ + +Proposed resolution:
++Replace 22.2.2.2.2 [facet.num.put.virtuals], paragraph 11, with the following +sentence: +
++ + ++For conversion from a floating-point type, +str.precision() is specified in the conversion +specification. +
Rationale:
+The floatfield determines whether numbers are formatted as if +with %f, %e, or %g. If the fixed bit is set, it's %f, +if scientific it's %e, and if both bits are set, or +neither, it's %g.
+Turning to the C standard, a precision of 0 is meaningful +for %f and %e. For %g, precision 0 is taken to be the same as +precision 1.
+The proposed resolution has the effect that if neither +fixed nor scientific is set we'll be +specifying a precision of 0, which will be internally +turned into 1. There's no need to call it out as a special +case.
+The output of the above program will be "1e+00".
+ +[Post-Curaçao: Howard provided improved wording covering the case +where precision is 0 and mode is %g.]
+ + + + + + + +Section: 17.4.3.2 [reserved.names] Status: WP + Submitter: Peter Dimov Date: 2000-04-18
+View all other issues in [reserved.names].
+View all issues with WP status.
+Discussion:
+17.4.3.1/1 uses the term "depends" to limit the set of allowed +specializations of standard templates to those that "depend on a +user-defined name of external linkage."
+This term, however, is not adequately defined, making it possible to +construct a specialization that is, I believe, technically legal according to +17.4.3.1/1, but that specializes a standard template for a built-in type such as +'int'.
+The following code demonstrates the problem:
+++ + +#include <algorithm>+template<class T> struct X +{ + typedef T type; +};+namespace std +{ + template<> void swap(::X<int>::type& i, ::X<int>::type& j); +}+
Proposed resolution:
+Change "user-defined name" to "user-defined +type".
+ + +Rationale:
+This terminology is used in section 2.5.2 and 4.1.1 of The C++ +Programming Language. It disallows the example in the issue, +since the underlying type itself is not user-defined. The only +possible problem I can see is for non-type templates, but there's no +possible way for a user to come up with a specialization for bitset, +for example, that might not have already been specialized by the +implementor?
+ +[Toronto: this may be related to issue 120.]
+ + +[post-Toronto: Judy provided the above proposed resolution and +rationale.]
+ + + + + + +Section: 23.1.4 [associative.reqmts] Status: WP + Submitter: Andrew Koenig Date: 2000-04-30
+View all other issues in [associative.reqmts].
+View all issues with WP status.
+ +Discussion:
++If mm is a multimap and p is an iterator +into the multimap, then mm.insert(p, x) inserts +x into mm with p as a hint as +to where it should go. Table 69 claims that the execution time is +amortized constant if the insert winds up taking place adjacent to +p, but does not say when, if ever, this is guaranteed to +happen. All it says it that p is a hint as to where to +insert. +
++The question is whether there is any guarantee about the relationship +between p and the insertion point, and, if so, what it +is. +
++I believe the present state is that there is no guarantee: The user +can supply p, and the implementation is allowed to +disregard it entirely. +
+ +Additional comments from Nathan:
+
+The vote [in Redmond] was on whether to elaborately specify the use of
+the hint, or to require behavior only if the value could be inserted
+adjacent to the hint. I would like to ensure that we have a chance to
+vote for a deterministic treatment: "before, if possible, otherwise
+after, otherwise anywhere appropriate", as an alternative to the
+proposed "before or after, if possible, otherwise [...]".
+
[Toronto: there was general agreement that this is a real defect: +when inserting an element x into a multiset that already contains +several copies of x, there is no way to know whether the hint will be +used. The proposed resolution was that the new element should always +be inserted as close to the hint as possible. So, for example, if +there is a subsequence of equivalent values, then providing a.begin() +as the hint means that the new element should be inserted before the +subsequence even if a.begin() is far away. JC van Winkel supplied +precise wording for this proposed resolution, and also for an +alternative resolution in which hints are only used when they are +adjacent to the insertion point.]
+ + +[Copenhagen: the LWG agreed to the original proposed resolution, +in which an insertion hint would be used even when it is far from the +insertion point. This was contingent on seeing a example +implementation showing that it is possible to implement this +requirement without loss of efficiency. John Potter provided such a +example implementation.]
+ + +[Redmond: The LWG was reluctant to adopt the proposal that +emerged from Copenhagen: it seemed excessively complicated, and went +beyond fixing the defect that we identified in Toronto. PJP provided +the new wording described in this issue. Nathan agrees that we +shouldn't adopt the more detailed semantics, and notes: "we know that +you can do it efficiently enough with a red-black tree, but there are +other (perhaps better) balanced tree techniques that might differ +enough to make the detailed semantics hard to satisfy."]
+ + +[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. +]
+ + +[ +Batavia: +1780 +accepted with minor wording changes in the proposed wording (reflected in the +proposed resolution below). Concerns about the performance of the algorithm +were satisfactorily met by +1780. +371 already handles the stability of equal ranges +and so that part of the resolution from +1780 +is no longer needed (or reflected in the proposed wording below). +]
+ + + + +Proposed resolution:
+ ++Change the indicated rows of the "Associative container requirements" Table in +23.1.4 [associative.reqmts] to: +
+ +expression | return type | +assertion/note pre/post-condition |
+complexity |
---|---|---|---|
a_eq.insert(t) | +iterator | ++inserts t and returns the iterator pointing to the newly inserted +element. If a range containing elements equivalent to t exists in +a_eq, t is inserted at the end of that range. + | ++logarithmic + |
a.insert(p,t) | +iterator | +
+inserts t if and only if there is no element with key equivalent to the
+key of t in containers with unique keys; always inserts t in containers
+with equivalent keys. always returns the iterator pointing to the element with key
+equivalent to the key of t. |
+
+logarithmic in general, but amortized constant if t is inserted right |
Section: 20.7.5.1 [allocator.members] Status: WP + Submitter: Dietmar Kühl Date: 2000-04-24
+View all other issues in [allocator.members].
+View all issues with WP status.
+Discussion:
+In paragraphs 12 and 13 the effects of construct() and +destruct() are described as returns but the functions actually +return void.
+ + +Proposed resolution:
+Substitute "Returns" by "Effect".
+ + + + +Section: 24.4.1.1 [reverse.iterator] Status: WP + Submitter: Dietmar Kühl Date: 2000-04-24
+View all issues with WP status.
+Discussion:
+The declaration of reverse_iterator lists a default +constructor. However, no specification is given what this constructor +should do.
+ + +Proposed resolution:
+In section 24.4.1.3.1 [reverse.iter.cons] add the following + paragraph:
+++reverse_iterator()
+ +Default initializes current. Iterator operations + applied to the resulting iterator have defined behavior if and + only if the corresponding operations are defined on a default + constructed iterator of type Iterator.
+
[pre-Copenhagen: Dietmar provide wording for proposed + resolution.]
+ + + + + + +Section: 23.2.2.1 [deque.cons] Status: WP + Submitter: Dietmar Kühl Date: 2000-04-24
+View all other issues in [deque.cons].
+View all issues with WP status.
+Discussion:
+The complexity specification in paragraph 6 says that the complexity +is linear in first - last. Even if operator-() is +defined on iterators this term is in general undefined because it +would have to be last - first.
+ + +Proposed resolution:
+Change paragraph 6 from
++Linear in first - last.
to become
++ + + + +Linear in distance(first, last).
Section: 27.7.1.1 [stringbuf.cons] Status: WP + Submitter: Dietmar Kühl Date: 2000-05-11
+View all issues with WP status.
+Discussion:
+In 27.7.1.1 paragraph 4 the results of calling the constructor of +'basic_stringbuf' are said to be str() == str. This is fine +that far but consider this code:
+ +std::basic_stringbuf<char> sbuf("hello, world", std::ios_base::openmode(0)); + std::cout << "'" << sbuf.str() << "'\n"; ++ +
Paragraph 3 of 27.7.1.1 basically says that in this case neither +the output sequence nor the input sequence is initialized and +paragraph 2 of 27.7.1.2 basically says that str() either +returns the input or the output sequence. None of them is initialized, +ie. both are empty, in which case the return from str() is +defined to be basic_string<cT>().
+ +However, probably only test cases in some testsuites will detect this +"problem"...
+ + +Proposed resolution:
+Remove 27.7.1.1 paragraph 4.
+ + +Rationale:
+We could fix 27.7.1.1 paragraph 4, but there would be no point. If +we fixed it, it would say just the same thing as text that's already +in the standard.
+ + + + +Section: 25.2.9 [alg.unique] Status: WP + Submitter: Angelika Langer Date: 2000-05-15
+View all other issues in [alg.unique].
+View all issues with WP status.
+Discussion:
+The complexity of unique and unique_copy are inconsistent with each +other and inconsistent with the implementations. The standard +specifies:
+ +for unique():
+ ++ +-3- Complexity: If the range (last - first) is not empty, exactly +(last - first) - 1 applications of the corresponding predicate, otherwise +no applications of the predicate.
for unique_copy():
+ ++ +-7- Complexity: Exactly last - first applications of the corresponding +predicate.
+The implementations do it the other way round: unique() applies the +predicate last-first times and unique_copy() applies it last-first-1 +times.
+ +As both algorithms use the predicate for pair-wise comparison of +sequence elements I don't see a justification for unique_copy() +applying the predicate last-first times, especially since it is not +specified to which pair in the sequence the predicate is applied +twice.
+ + +Proposed resolution:
+Change both complexity sections in 25.2.9 [alg.unique] to:
+ ++ + + + + + +Complexity: For nonempty ranges, exactly last - first - 1 +applications of the corresponding predicate.
Section: 25.1.8 [alg.adjacent.find] Status: WP + Submitter: Angelika Langer Date: 2000-05-15
+View all issues with WP status.
+Discussion:
+The complexity section of adjacent_find is defective:
+ +++ +template <class ForwardIterator> +ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last + BinaryPredicate pred); ++ +-1- Returns: The first iterator i such that both i and i + 1 are in +the range [first, last) for which the following corresponding +conditions hold: *i == *(i + 1), pred(*i, *(i + 1)) != false. Returns +last if no such iterator is found.
+ +-2- Complexity: Exactly find(first, last, value) - first applications +of the corresponding predicate. +
+
In the Complexity section, it is not defined what "value" +is supposed to mean. My best guess is that "value" means an +object for which one of the conditions pred(*i,value) or +pred(value,*i) is true, where i is the iterator defined in the Returns +section. However, the value type of the input sequence need not be +equality-comparable and for this reason the term find(first, last, +value) - first is meaningless.
+ +A term such as find_if(first, last, bind2nd(pred,*i)) - first or +find_if(first, last, bind1st(pred,*i)) - first might come closer to +the intended specification. Binders can only be applied to function +objects that have the function call operator declared const, which is +not required of predicates because they can have non-const data +members. For this reason, a specification using a binder could only be +an "as-if" specification.
+ + +Proposed resolution:
+Change the complexity section in 25.1.8 [alg.adjacent.find] to:
++ ++For a nonempty range, exactly min((i - first) + 1, +(last - first) - 1) applications of the +corresponding predicate, where i is adjacent_find's +return value. +
[Copenhagen: the original resolution specified an upper +bound. The LWG preferred an exact count.]
+ + + + + + + +Section: 25.2.9 [alg.unique] Status: WP + Submitter: Angelika Langer Date: 2000-05-15
+View all other issues in [alg.unique].
+View all issues with WP status.
+Discussion:
+ +Some popular implementations of unique_copy() create temporary +copies of values in the input sequence, at least if the input iterator +is a pointer. Such an implementation is built on the assumption that +the value type is CopyConstructible and Assignable.
+ +It is common practice in the standard that algorithms explicitly +specify any additional requirements that they impose on any of the +types used by the algorithm. An example of an algorithm that creates +temporary copies and correctly specifies the additional requirements +is accumulate(), 26.4.1 [rand.req].
+ +Since the specifications of unique() and unique_copy() do not +require CopyConstructible and Assignable of the InputIterator's value +type the above mentioned implementations are not standard-compliant. I +cannot judge whether this is a defect in the standard or a defect in +the implementations.
+ + +Proposed resolution:
+In 25.2.8 change:
+ ++ ++-4- Requires: The ranges [first, last) and [result, result+(last-first)) +shall not overlap. +
to:
+ +++ +-4- Requires: The ranges [first, last) and [result, + result+(last-first)) shall not overlap. The expression *result = + *first must be valid. If neither InputIterator nor OutputIterator + meets the requirements of forward iterator then the value type of + InputIterator must be copy constructible. Otherwise copy + constructible is not required.
+
[Redmond: the original proposed resolution didn't impose an +explicit requirement that the iterator's value type must be copy +constructible, on the grounds that an input iterator's value type must +always be copy constructible. Not everyone in the LWG thought that +this requirement was clear from table 72. It has been suggested that +it might be possible to implement unique_copy without +requiring assignability, although current implementations do impose +that requirement. Howard provided new wording.]
+ + +[ +Curaçao: The LWG changed the PR editorially to specify +"neither...nor...meet..." as clearer than +"both...and...do not meet...". Change believed to be so +minor as not to require re-review. +]
+ + + + + + + + +Section: 25.2.4 [alg.transform], 26.4 [rand] Status: WP + Submitter: Angelika Langer Date: 2000-05-15
+View all other issues in [alg.transform].
+View all issues with WP status.
+Discussion:
+The algorithms transform(), accumulate(), inner_product(), +partial_sum(), and adjacent_difference() require that the function +object supplied to them shall not have any side effects.
+ +The standard defines a side effect in 1.9 [intro.execution] as:
++ +-7- Accessing an object designated by a volatile lvalue (basic.lval), +modifying an object, calling a library I/O function, or calling a function +that does any of those operations are all side effects, which are changes +in the state of the execution environment.
As a consequence, the function call operator of a function object supplied +to any of the algorithms listed above cannot modify data members, cannot +invoke any function that has a side effect, and cannot even create and +modify temporary objects. It is difficult to imagine a function object +that is still useful under these severe limitations. For instance, any +non-trivial transformator supplied to transform() might involve creation +and modification of temporaries, which is prohibited according to the current +wording of the standard.
+ +On the other hand, popular implementations of these algorithms exhibit +uniform and predictable behavior when invoked with a side-effect-producing +function objects. It looks like the strong requirement is not needed for +efficient implementation of these algorithms.
+ +The requirement of side-effect-free function objects could be +replaced by a more relaxed basic requirement (which would hold for all +function objects supplied to any algorithm in the standard library):
++ +A function objects supplied to an algorithm shall not invalidate +any iterator or sequence that is used by the algorithm. Invalidation of +the sequence includes destruction of the sorting order if the algorithm +relies on the sorting order (see section 25.3 - Sorting and related operations +[lib.alg.sorting]).
I can't judge whether it is intended that the function objects supplied +to transform(), accumulate(), inner_product(), partial_sum(), or adjacent_difference() +shall not modify sequence elements through dereferenced iterators.
+ +It is debatable whether this issue is a defect or a change request. +Since the consequences for user-supplied function objects are drastic and +limit the usefulness of the algorithms significantly I would consider it +a defect.
+ + +Proposed resolution:
+ +Things to notice about these changes:
+ +Change 25.2.3/2 from:
+ ++ ++ -2- Requires: op and binary_op shall not have any side effects. +
to:
+ ++ + ++ -2- Requires: in the ranges [first1, last1], [first2, first2 + + (last1 - first1)] and [result, result + (last1- first1)], op and + binary_op shall neither modify elements nor invalidate iterators or + subranges. + [Footnote: The use of fully closed ranges is intentional --end footnote] +
Change 25.2.3/2 from:
+ ++ ++ -2- Requires: op and binary_op shall not have any side effects. +
to:
+ ++ + ++ -2- Requires: op and binary_op shall not invalidate iterators or + subranges, or modify elements in the ranges [first1, last1], + [first2, first2 + (last1 - first1)], and [result, result + (last1 + - first1)]. + [Footnote: The use of fully closed ranges is intentional --end footnote] +
Change 26.4.1/2 from:
+ ++ ++ -2- Requires: T must meet the requirements of CopyConstructible + (lib.copyconstructible) and Assignable (lib.container.requirements) + types. binary_op shall not cause side effects. +
to:
+ ++ ++ -2- Requires: T must meet the requirements of CopyConstructible + (lib.copyconstructible) and Assignable + (lib.container.requirements) types. In the range [first, last], + binary_op shall neither modify elements nor invalidate iterators + or subranges. + [Footnote: The use of a fully closed range is intentional --end footnote] +
Change 26.4.2/2 from:
+ ++ ++ -2- Requires: T must meet the requirements of CopyConstructible + (lib.copyconstructible) and Assignable (lib.container.requirements) + types. binary_op1 and binary_op2 shall not cause side effects. +
to:
+ ++ + ++ -2- Requires: T must meet the requirements of CopyConstructible + (lib.copyconstructible) and Assignable (lib.container.requirements) + types. In the ranges [first, last] and [first2, first2 + (last - + first)], binary_op1 and binary_op2 shall neither modify elements + nor invalidate iterators or subranges. + [Footnote: The use of fully closed ranges is intentional --end footnote] +
Change 26.4.3/4 from:
+ ++ ++ -4- Requires: binary_op is expected not to have any side effects. +
to:
+ ++ ++ -4- Requires: In the ranges [first, last] and [result, result + + (last - first)], binary_op shall neither modify elements nor + invalidate iterators or subranges. + [Footnote: The use of fully closed ranges is intentional --end footnote] +
Change 26.4.4/2 from:
+ ++ ++ -2- Requires: binary_op shall not have any side effects. +
to:
+ ++ ++ -2- Requires: In the ranges [first, last] and [result, result + + (last - first)], binary_op shall neither modify elements nor + invalidate iterators or subranges. + [Footnote: The use of fully closed ranges is intentional --end footnote] +
[Toronto: Dave Abrahams supplied wording.]
+ + +[Copenhagen: Proposed resolution was modified slightly. Matt +added footnotes pointing out that the use of closed ranges was +intentional.]
+ + + + + + + +Section: 27.6.1.3 [istream.unformatted] Status: WP + Submitter: Martin Sebor Date: 2000-05-15
+View all other issues in [istream.unformatted].
+View all issues with WP status.
+Discussion:
+basic_istream<>::get(), and basic_istream<>::getline(), +are unclear with respect to the behavior and side-effects of the named +functions in case of an error.
+ +27.6.1.3, p1 states that "... If the sentry object returns +true, when converted to a value of type bool, the function endeavors +to obtain the requested input..." It is not clear from this (or +the rest of the paragraph) what precisely the behavior should be when +the sentry ctor exits by throwing an exception or when the sentry +object returns false. In particular, what is the number of characters +extracted that gcount() returns supposed to be?
+ +27.6.1.3 p8 and p19 say about the effects of get() and getline(): +"... In any case, it then stores a null character (using +charT()) into the next successive location of the array." Is not +clear whether this sentence applies if either of the conditions above +holds (i.e., when sentry fails).
+ + +Proposed resolution:
+Add to 27.6.1.3, p1 after the sentence
+ ++ ++"... If the sentry object returns true, when converted to a value of +type bool, the function endeavors to obtain the requested input." +
the following
+ + ++ + ++"Otherwise, if the sentry constructor exits by throwing an exception or +if the sentry object returns false, when converted to a value of type +bool, the function returns without attempting to obtain any input. In +either case the number of extracted characters is set to 0; unformatted +input functions taking a character array of non-zero size as an argument +shall also store a null character (using charT()) in the first location +of the array." +
Rationale:
+Although the general philosophy of the input functions is that the +argument should not be modified upon failure, getline +historically added a terminating null unconditionally. Most +implementations still do that. Earlier versions of the draft standard +had language that made this an unambiguous requirement; those words +were moved to a place where their context made them less clear. See +Jerry Schwarz's message c++std-lib-7618.
+ + + + +Section: 23.2.6.4 [vector.modifiers] Status: WP + Submitter: Lisa Lippincott Date: 2000-06-06
+View all other issues in [vector.modifiers].
+View all issues with WP status.
+Discussion:
+Paragraph 2 of 23.2.6.4 [vector.modifiers] describes the complexity +of vector::insert:
+ ++ ++ Complexity: If first and last are forward iterators, bidirectional + iterators, or random access iterators, the complexity is linear in + the number of elements in the range [first, last) plus the distance + to the end of the vector. If they are input iterators, the complexity + is proportional to the number of elements in the range [first, last) + times the distance to the end of the vector. +
First, this fails to address the non-iterator forms of +insert.
+ +Second, the complexity for input iterators misses an edge case -- +it requires that an arbitrary number of elements can be added at +the end of a vector in constant time.
+ +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.2.3 [deque.modifiers], +paragraph 3):
+ ++ + ++ Complexity: In the worst case, inserting a single element into a + deque takes time linear in the minimum of the distance from the + insertion point to the beginning of the deque and the distance + from the insertion point to the end of the deque. Inserting a + single element either at the beginning or end of a deque always + takes constant time and causes a single call to the copy constructor + of T. +
Proposed resolution:
+ +Change Paragraph 2 of 23.2.6.4 [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.]
+ + +Change 23.2.2.3 [deque.modifiers], paragraph 3, to:
+ ++ + + ++ Complexity: The complexity is linear in the number of elements + inserted plus the shorter of the distances to the beginning and + end of the deque. Inserting a single element at either the + beginning or the end of a deque causes a single call to the copy + constructor of T. +
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: 22.2.5 [category.time] Status: WP + Submitter: Martin Sebor Date: 2000-06-22
+View all issues with WP status.
+Discussion:
+There is no requirement that any of time_get member functions set +ios::eofbit when they reach the end iterator while parsing their input. +Since members of both the num_get and money_get facets are required to +do so (22.2.2.1.2, and 22.2.6.1.2, respectively), time_get members +should follow the same requirement for consistency.
+ + +Proposed resolution:
+Add paragraph 2 to section 22.2.5.1 with the following text:
+ ++ + ++If the end iterator is reached during parsing by any of the get() +member functions, the member sets ios_base::eofbit in err. +
Rationale:
+Two alternative resolutions were proposed. The LWG chose this one +because it was more consistent with the way eof is described for other +input facets.
+ + + + +Section: 23.2.4.4 [list.ops] Status: WP + Submitter: Brian Parker Date: 2000-07-14
+View all other issues in [list.ops].
+View all issues with WP status.
+Discussion:
++Section 23.2.4.4 [list.ops] states that +
+void splice(iterator position, list<T, Allocator>& x); ++
+invalidates all iterators and references to list x. +
+ ++This is unnecessary and defeats an important feature of splice. In +fact, the SGI STL guarantees that iterators to x remain valid +after splice. +
+ + +Proposed resolution:
+ +Add a footnote to 23.2.4.4 [list.ops], paragraph 1:
++ ++[Footnote: As specified in [default.con.req], paragraphs +4-5, the semantics described in this clause applies only to the case +where allocators compare equal. --end footnote] +
In 23.2.4.4 [list.ops], replace paragraph 4 with:
++ ++Effects: Inserts the contents of x before position and x becomes +empty. Pointers and references to the moved elements of x now refer to +those same elements but as members of *this. Iterators referring to the +moved elements will continue to refer to their elements, but they now +behave as iterators into *this, not into x. +
In 23.2.4.4 [list.ops], replace paragraph 7 with:
++ ++Effects: Inserts an element pointed to by i from list x before +position and removes the element from x. The result is unchanged if +position == i or position == ++i. Pointers and references to *i continue +to refer to this same element but as a member of *this. Iterators to *i +(including i itself) continue to refer to the same element, but now +behave as iterators into *this, not into x. +
In 23.2.4.4 [list.ops], replace paragraph 12 with:
++ ++Requires: [first, last) is a valid range in x. The result is +undefined if position is an iterator in the range [first, last). +Pointers and references to the moved elements of x now refer to those +same elements but as members of *this. Iterators referring to the moved +elements will continue to refer to their elements, but they now behave as +iterators into *this, not into x. +
[pre-Copenhagen: Howard provided wording.]
+ + + +Rationale:
+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 [default.con.req] paragraph 4, the behavior of list when +allocators compare nonequal is outside the scope of the standard.
+ + + + +Section: 27.7.1 [stringbuf] Status: WP + Submitter: Martin Sebor Date: 2000-07-28
+View all issues with WP status.
+Discussion:
+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 +the allocator at compile time. It's also inconsistent with all other +template classes in the library that do provide a typedef for the +Allocator parameter.
+ + +Proposed resolution:
+Add to the synopses of the class templates basic_stringbuf (27.7.1), +basic_istringstream (27.7.2), basic_ostringstream (27.7.3), and +basic_stringstream (27.7.4) the typedef:
+typedef Allocator allocator_type; ++ + + + +
Section: 27.7 [string.streams] Status: WP + Submitter: Martin Sebor Date: 2000-07-28
+View all other issues in [string.streams].
+View all issues with WP status.
+Discussion:
+27.7.2.2, p1 uses a C-style cast rather than the more appropriate +const_cast<> in the Returns clause for basic_istringstream<>::rdbuf(). +The same C-style cast is being used in 27.7.3.2, p1, D.7.2.2, p1, and +D.7.3.2, p1, and perhaps elsewhere. 27.7.6, p1 and D.7.2.2, p1 are missing +the cast altogether.
+ +C-style casts have not been deprecated, so the first part of this +issue is stylistic rather than a matter of correctness.
+ + +Proposed resolution:
+In 27.7.2.2, p1 replace
+-1- Returns: (basic_stringbuf<charT,traits,Allocator>*)&sb.+ +
with
+-1- Returns: const_cast<basic_stringbuf<charT,traits,Allocator>*>(&sb).+ + +
In 27.7.3.2, p1 replace
+-1- Returns: (basic_stringbuf<charT,traits,Allocator>*)&sb.+ +
with
+-1- Returns: const_cast<basic_stringbuf<charT,traits,Allocator>*>(&sb).+ +
In 27.7.6, p1, replace
+-1- Returns: &sb+ +
with
+-1- Returns: const_cast<basic_stringbuf<charT,traits,Allocator>*>(&sb).+ +
In D.7.2.2, p1 replace
+-2- Returns: &sb.+ +
with
+-2- Returns: const_cast<strstreambuf*>(&sb).+ + + + +
Section: 26.5.2.1 [valarray.cons], 26.5.2.2 [valarray.assign] Status: WP + Submitter: Robert Klarer Date: 2000-07-31
+View other active issues in [valarray.cons].
+View all other issues in [valarray.cons].
+View all issues with WP status.
+Discussion:
+This discussion is adapted from message c++std-lib-7056 posted +November 11, 1999. I don't think that anyone can reasonably claim +that the problem described below is NAD.
+ +These valarray constructors can never be called:
+ +template <class T> + valarray<T>::valarray(const slice_array<T> &); + template <class T> + valarray<T>::valarray(const gslice_array<T> &); + template <class T> + valarray<T>::valarray(const mask_array<T> &); + template <class T> + valarray<T>::valarray(const indirect_array<T> &); ++ +
Similarly, these valarray assignment operators cannot be +called:
+ +template <class T> + valarray<T> valarray<T>::operator=(const slice_array<T> &); + template <class T> + valarray<T> valarray<T>::operator=(const gslice_array<T> &); + template <class T> + valarray<T> valarray<T>::operator=(const mask_array<T> &); + template <class T> + valarray<T> valarray<T>::operator=(const indirect_array<T> &); ++ +
Please consider the following example:
+ +#include <valarray> + using namespace std; + + int main() + { + valarray<double> va1(12); + valarray<double> va2(va1[slice(1,4,3)]); // line 1 + } ++ + +
Since the valarray va1 is non-const, the result of the sub-expression +va1[slice(1,4,3)] at line 1 is an rvalue of type const +std::slice_array<double>. This slice_array rvalue is then used to +construct va2. The constructor that is used to construct va2 is +declared like this:
+ +template <class T> + valarray<T>::valarray(const slice_array<T> &); ++ +
Notice the constructor's const reference parameter. When the +constructor is called, a slice_array must be bound to this reference. +The rules for binding an rvalue to a const reference are in 8.5.3, +paragraph 5 (see also 13.3.3.1.4). Specifically, paragraph 5 +indicates that a second slice_array rvalue is constructed (in this +case copy-constructed) from the first one; it is this second rvalue +that is bound to the reference parameter. Paragraph 5 also requires +that the constructor that is used for this purpose be callable, +regardless of whether the second rvalue is elided. The +copy-constructor in this case is not callable, however, because it is +private. Therefore, the compiler should report an error.
+ +Since slice_arrays are always rvalues, the valarray constructor that has a +parameter of type const slice_array<T> & can never be called. The +same reasoning applies to the three other constructors and the four +assignment operators that are listed at the beginning of this post. +Furthermore, since these functions cannot be called, the valarray helper +classes are almost entirely useless.
+ + +Proposed resolution:
+slice_array:
+gslice_array:
+mask_array:
+indirect_array:
+[Proposed resolution was modified in Santa Cruz: explicitly make +copy constructor and copy assignment operators public, instead of +removing them.]
+ + + +Rationale:
+Keeping the valarray constructors private is untenable. Merely +making valarray a friend of the helper classes isn't good enough, +because access to the copy constructor is checked in the user's +environment.
+ +Making the assignment operator public is not strictly necessary to +solve this problem. A majority of the LWG (straw poll: 13-4) +believed we should make the assignment operators public, in addition +to the copy constructors, for reasons of symmetry and user +expectation.
+ + + + + +Section: 19.1 [std.exceptions], 27.4.2.1.1 [ios::failure] Status: WP + Submitter: Dave Abrahams Date: 2000-08-01
+View all issues with WP status.
+Discussion:
++Many of the standard exception types which implementations are +required to throw are constructed with a const std::string& +parameter. For example: +
+ +19.1.5 Class out_of_range [lib.out.of.range] + namespace std { + class out_of_range : public logic_error { + public: + explicit out_of_range(const string& what_arg); + }; + } + + 1 The class out_of_range defines the type of objects thrown as excep- + tions to report an argument value not in its expected range. + + out_of_range(const string& what_arg); + + Effects: + Constructs an object of class out_of_range. + Postcondition: + strcmp(what(), what_arg.c_str()) == 0. ++ +
+There are at least two problems with this: +
++There may be no cure for (1) other than changing the interface to +out_of_range, though one could reasonably argue that (1) is not a +defect. Personally I don't care that much if out-of-memory is reported +when I only have 20 bytes left, in the case when out_of_range would +have been reported. People who use exception-specifications might care +a lot, though. +
+ ++There is a cure for (2), but it isn't completely obvious. I think a +note for implementors should be made in the standard. Avoiding +possible termination in this case shouldn't be left up to chance. The +cure is to use a reference-counted "string" implementation +in the exception object. I am not necessarily referring to a +std::string here; any simple reference-counting scheme for a NTBS +would do. +
+ +Further discussion, in email:
+ ++...I'm not so concerned about (1). After all, a library implementation +can add const char* constructors as an extension, and users don't +need to avail themselves of the standard exceptions, though this is +a lame position to be forced into. FWIW, std::exception and +std::bad_alloc don't require a temporary basic_string. +
+ +
+...I don't think the fixed-size buffer is a solution to the problem,
+strictly speaking, because you can't satisfy the postcondition
+
+ strcmp(what(), what_arg.c_str()) == 0
+
+For all values of what_arg (i.e. very long values). That means that
+the only truly conforming solution requires a dynamic allocation.
+
Further discussion, from Redmond:
+ +The most important progress we made at the Redmond meeting was +realizing that there are two separable issues here: the const +string& constructor, and the copy constructor. If a user writes +something like throw std::out_of_range("foo"), the const +string& constructor is invoked before anything gets thrown. The +copy constructor is potentially invoked during stack unwinding.
+ +The copy constructor is a more serious problem, becuase failure +during stack unwinding invokes terminate. The copy +constructor must be nothrow. Curaçao: Howard thinks this +requirement may already be present.
+ +The fundamental problem is that it's difficult to get the nothrow +requirement to work well with the requirement that the exception +objects store a string of unbounded size, particularly if you also try +to make the const string& constructor nothrow. Options discussed +include:
+ +(Not all of these options are mutually exclusive.)
+ + + +Proposed resolution:
+ ++Change 19.1.1 [logic.error] +
+ +++ +namespace std { + class logic_error : public exception { + public: + explicit logic_error(const string& what_arg); + explicit logic_error(const char* what_arg); + }; +} ++...
++logic_error(const char* what_arg); +
+++ ++-4- Effects: Constructs an object of class logic_error. +
++-5- Postcondition: strcmp(what(), what_arg) == 0. +
+
+Change 19.1.2 [domain.error] +
+ +++ +namespace std { + class domain_error : public logic_error { + public: + explicit domain_error(const string& what_arg); + explicit domain_error(const char* what_arg); + }; +} ++...
++domain_error(const char* what_arg); +
++++-4- Effects: Constructs an object of class domain_error. +
++-5- Postcondition: strcmp(what(), what_arg) == 0. +
+ +
+Change 19.1.3 [invalid.argument] +
+ +++ +namespace std { + class invalid_argument : public logic_error { + public: + explicit invalid_argument(const string& what_arg); + explicit invalid_argument(const char* what_arg); + }; +} ++...
++invalid_argument(const char* what_arg); +
+++ ++-4- Effects: Constructs an object of class invalid_argument. +
++-5- Postcondition: strcmp(what(), what_arg) == 0. +
+
+Change 19.1.4 [length.error] +
+ +++ +namespace std { + class length_error : public logic_error { + public: + explicit length_error(const string& what_arg); + explicit length_error(const char* what_arg); + }; +} ++...
++length_error(const char* what_arg); +
+++ ++-4- Effects: Constructs an object of class length_error. +
++-5- Postcondition: strcmp(what(), what_arg) == 0. +
+
+Change 19.1.5 [out.of.range] +
+ +++ +namespace std { + class out_of_range : public logic_error { + public: + explicit out_of_range(const string& what_arg); + explicit out_of_range(const char* what_arg); + }; +} ++...
++out_of_range(const char* what_arg); +
+++ ++-4- Effects: Constructs an object of class out_of_range. +
++-5- Postcondition: strcmp(what(), what_arg) == 0. +
+
+Change 19.1.6 [runtime.error] +
+ +++ +namespace std { + class runtime_error : public exception { + public: + explicit runtime_error(const string& what_arg); + explicit runtime_error(const char* what_arg); + }; +} ++...
++runtime_error(const char* what_arg); +
+++ ++-4- Effects: Constructs an object of class runtime_error. +
++-5- Postcondition: strcmp(what(), what_arg) == 0. +
+
+Change 19.1.7 [range.error] +
+ +++ +namespace std { + class range_error : public runtime_error { + public: + explicit range_error(const string& what_arg); + explicit range_error(const char* what_arg); + }; +} ++...
++range_error(const char* what_arg); +
+++ ++-4- Effects: Constructs an object of class range_error. +
++-5- Postcondition: strcmp(what(), what_arg) == 0. +
+
+Change 19.1.8 [overflow.error] +
+ +++ +namespace std { + class overflow_error : public runtime_error { + public: + explicit overflow_error(const string& what_arg); + explicit overflow_error(const char* what_arg); + }; +} ++...
++overflow_error(const char* what_arg); +
+++ ++-4- Effects: Constructs an object of class overflow_error. +
++-5- Postcondition: strcmp(what(), what_arg) == 0. +
+
+Change 19.1.9 [underflow.error] +
+ +++ +namespace std { + class underflow_error : public runtime_error { + public: + explicit underflow_error(const string& what_arg); + explicit underflow_error(const char* what_arg); + }; +} ++...
++underflow_error(const char* what_arg); +
+++ ++-4- Effects: Constructs an object of class underflow_error. +
++-5- Postcondition: strcmp(what(), what_arg) == 0. +
+
+Change 27.4.2.1.1 [ios::failure] +
+ +++ + + +namespace std { + class ios_base::failure : public exception { + public: + explicit failure(const string& msg); + explicit failure(const char* msg); + virtual const char* what() const throw(); +}; +} ++...
++failure(const char* msg); +
+++ ++-4- Effects: Constructs an object of class failure. +
++-5- Postcondition: strcmp(what(), msg) == 0. +
+
Rationale:
+ +Throwing a bad_alloc while trying to construct a message for another +exception-derived class is not necessarily a bad thing. And the +bad_alloc constructor already has a no throw spec on it (18.4.2.1).
+ +Future:
+ +All involved would like to see const char* constructors added, but +this should probably be done for C++0X as opposed to a DR.
+ +I believe the no throw specs currently decorating these functions +could be improved by some kind of static no throw spec checking +mechanism (in a future C++ language). As they stand, the copy +constructors might fail via a call to unexpected. I think what is +intended here is that the copy constructors can't fail.
+ +[Pre-Sydney: reopened at the request of Howard Hinnant. + Post-Redmond: James Kanze noticed that the copy constructors of + exception-derived classes do not have nothrow clauses. Those + classes have no copy constructors declared, meaning the + compiler-generated implicit copy constructors are used, and those + compiler-generated constructors might in principle throw anything.]
+ + +[ +Batavia: Merged copy constructor and assignment operator spec into exception +and added ios::failure into the proposed resolution. +]
+ + +[ +Oxford: The proposed resolution simply addresses the issue of constructing +the exception objects with const char* and string literals without +the need to explicit include or construct a std::string. +]
+ + + + + + + +Section: 27.4.4.2 [basic.ios.members] Status: WP + Submitter: Martin Sebor Date: 2000-08-21
+View other active issues in [basic.ios.members].
+View all other issues in [basic.ios.members].
+View all issues with WP status.
+Discussion:
++27.4.4.2, p17 says +
+ ++ ++-17- Before copying any parts of rhs, calls each registered callback +pair (fn,index) as (*fn)(erase_event,*this,index). After all parts but +exceptions() have been replaced, calls each callback pair that was +copied from rhs as (*fn)(copy_event,*this,index). +
+The name copy_event isn't defined anywhere. The intended name was +copyfmt_event. +
+ + +Proposed resolution:
+Replace copy_event with copyfmt_event in the named paragraph.
+ + + + +Section: 20.1.2 [allocator.requirements] Status: WP + Submitter: Matt Austern Date: 2000-08-22
+View other active issues in [allocator.requirements].
+View all other issues in [allocator.requirements].
+View all issues with WP status.
+Discussion:
++From lib-7752: +
+ ++I've been assuming (and probably everyone else has been assuming) that +allocator instances have a particular property, and I don't think that +property can be deduced from anything in Table 32. +
+ ++I think we have to assume that allocator type conversion is a +homomorphism. That is, if x1 and x2 are of type X, where +X::value_type is T, and if type Y is X::template +rebind<U>::other, then Y(x1) == Y(x2) if and only if x1 == x2. +
+ ++Further discussion: Howard Hinnant writes, in lib-7757: +
+ ++I think I can prove that this is not provable by Table 32. And I agree +it needs to be true except for the "and only if". If x1 != x2, I see no +reason why it can't be true that Y(x1) == Y(x2). Admittedly I can't +think of a practical instance where this would happen, or be valuable. +But I also don't see a need to add that extra restriction. I think we +only need: +
+ ++ ++ if (x1 == x2) then Y(x1) == Y(x2) +
+If we decide that == on allocators is transitive, then I think I can +prove the above. But I don't think == is necessarily transitive on +allocators. That is: +
+ ++Given x1 == x2 and x2 == x3, this does not mean x1 == x3. +
+ +Example:
+ ++++x1 can deallocate pointers from: x1, x2, x3
+ +
+x2 can deallocate pointers from: x1, x2, x4
+x3 can deallocate pointers from: x1, x3
+x4 can deallocate pointers from: x2, x4 ++x1 == x2, and x2 == x4, but x1 != x4 +
+
[Toronto: LWG members offered multiple opinions. One +opinion is that it should not be required that x1 == x2 +implies Y(x1) == Y(x2), and that it should not even be +required that X(x1) == x1. Another opinion is that +the second line from the bottom in table 32 already implies the +desired property. This issue should be considered in light of +other issues related to allocator instances.]
+ + + +Proposed resolution:
++Accept proposed wording from +N2436 part 3. +
+ + +[Lillehammer: Same conclusion as before: this should be + considered as part of an allocator redesign, not solved on its own.]
+ + +[ +Batavia: An allocator redesign is not forthcoming and thus we fixed this one issue. +]
+ + +[ +Toronto: Reopened at the request of the project editor (Pete) because the proposed +wording did not fit within the indicated table. The intent of the resolution remains +unchanged. Pablo to work with Pete on improved wording. +]
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2387 for this issue which +was subsequently split out into a separate paper N2436 for the purposes of voting. +The resolution in N2436 addresses this issue. The LWG voted to accelerate this +issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 21.3.4 [string.capacity] Status: WP + Submitter: Chris Newton Date: 2000-08-27
+View all other issues in [string.capacity].
+View all issues with WP status.
+Discussion:
++Paraphrased from a message that Chris Newton posted to comp.std.c++: +
+ ++The standard's description of basic_string<>::operator[] +seems to violate const correctness. +
+ ++The standard (21.3.4/1) says that "If pos < size(), +returns data()[pos]." The types don't work. The +return value of data() is const charT*, but +operator[] has a non-const version whose return type is reference. +
+ + +Proposed resolution:
++In section 21.3.4, paragraph 1, change +"data()[pos]" to "*(begin() + +pos)". +
+ + + + +Section: 24.5.1.2 [istream.iterator.ops] Status: WP + Submitter: Martin Sebor Date: 2000-08-27
+View all other issues in [istream.iterator.ops].
+View all issues with WP status.
+Discussion:
+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 +given the Effects clause below (since a temporary is returned). The +`&' is probably just a typo.
+ + +Proposed resolution:
+Change the declaration in 24.5.1.2, p5 from
+istream_iterator<T,charT,traits,Distance>& operator++(int); ++
to
+istream_iterator<T,charT,traits,Distance> operator++(int); ++
(that is, remove the `&').
+ + + + +Section: 24.5.1.2 [istream.iterator.ops] Status: WP + Submitter: Martin Sebor Date: 2000-08-27
+View all other issues in [istream.iterator.ops].
+View all issues with WP status.
+Discussion:
++24.5.1, p3 lists the synopsis for +
+ +template <class T, class charT, class traits, class Distance> + bool operator!=(const istream_iterator<T,charT,traits,Distance>& x, + const istream_iterator<T,charT,traits,Distance>& y); ++ +
+but there is no description of what the operator does (i.e., no Effects +or Returns clause) in 24.5.1.2. +
+ + +Proposed resolution:
++Add paragraph 7 to the end of section 24.5.1.2 with the following text: +
+ +template <class T, class charT, class traits, class Distance> + bool operator!=(const istream_iterator<T,charT,traits,Distance>& x, + const istream_iterator<T,charT,traits,Distance>& y); ++ +
-7- Returns: !(x == y).
+ + + + +Section: 17.3.2.1.2 [bitmask.types] Status: WP + Submitter: Beman Dawes Date: 2000-09-03
+View all issues with WP status.
+Discussion:
++The ~ operation should be applied after the cast to int_type. +
+ + +Proposed resolution:
++Change 17.3.2.1.2 [lib.bitmask.types] operator~ from: +
+ +bitmask operator~ ( bitmask X ) + { return static_cast< bitmask>(static_cast<int_type>(~ X)); } ++ +
+to: +
+ +bitmask operator~ ( bitmask X ) + { return static_cast< bitmask>(~static_cast<int_type>(X)); } ++ + + + +
Section: 21.3 [basic.string] Status: WP + Submitter: Kevlin Henney Date: 2000-09-04
+View other active issues in [basic.string].
+View all other issues in [basic.string].
+View all issues with WP status.
+Discussion:
++The note in paragraph 6 suggests that the invalidation rules for +references, pointers, and iterators in paragraph 5 permit a reference- +counted implementation (actually, according to paragraph 6, they permit +a "reference counted implementation", but this is a minor editorial fix). +
+ ++However, the last sub-bullet is so worded as to make a reference-counted +implementation unviable. In the following example none of the +conditions for iterator invalidation are satisfied: +
+ +// first example: "*******************" should be printed twice + string original = "some arbitrary text", copy = original; + const string & alias = original; + + string::const_iterator i = alias.begin(), e = alias.end(); + for(string::iterator j = original.begin(); j != original.end(); ++j) + *j = '*'; + while(i != e) + cout << *i++; + cout << endl; + cout << original << endl; ++ +
+Similarly, in the following example: +
+ +// second example: "some arbitrary text" should be printed out + string original = "some arbitrary text", copy = original; + const string & alias = original; + + string::const_iterator i = alias.begin(); + original.begin(); + while(i != alias.end()) + cout << *i++; ++ +
+I have tested this on three string implementations, two of which were +reference counted. The reference-counted implementations gave +"surprising behavior" because they invalidated iterators on +the first call to non-const begin since construction. The current +wording does not permit such invalidation because it does not take +into account the first call since construction, only the first call +since various member and non-member function calls. +
+ + +Proposed resolution:
++Change the following sentence in 21.3 paragraph 5 from +
+ ++ ++ Subsequent to any of the above uses except the forms of insert() and + erase() which return iterators, the first call to non-const member + functions operator[](), at(), begin(), rbegin(), end(), or rend(). +
to
+ ++ + + + ++ Following construction or any of the above uses, except the forms of + insert() and erase() that return iterators, the first call to non- + const member functions operator[](), at(), begin(), rbegin(), end(), + or rend(). +
Section: 23.1.4 [associative.reqmts] Status: WP + Submitter: John Potter Date: 2000-09-07
+View all other issues in [associative.reqmts].
+View all issues with WP status.
+Duplicate of: 102
+Discussion:
++Table 69 requires linear time if [i, j) is sorted. Sorted is necessary but not sufficient. +Consider inserting a sorted range of even integers into a set<int> containing the odd +integers in the same range. +
+ +Related issue: 102
+ + +Proposed resolution:
++In Table 69, in section 23.1.2, change the complexity clause for +insertion of a range from "N log(size() + N) (N is the distance +from i to j) in general; linear if [i, j) is sorted according to +value_comp()" to "N log(size() + N), where N is the distance +from i to j". +
+ +[Copenhagen: Minor fix in proposed resolution: fixed unbalanced +parens in the revised wording.]
+ + + + +Rationale:
++Testing for valid insertions could be less efficient than simply +inserting the elements when the range is not both sorted and between +two adjacent existing elements; this could be a QOI issue. +
+ ++The LWG considered two other options: (a) specifying that the +complexity was linear if [i, j) is sorted according to value_comp() +and between two adjacent existing elements; or (b) changing to +Klog(size() + N) + (N - K) (N is the distance from i to j and K is the +number of elements which do not insert immediately after the previous +element from [i, j) including the first). The LWG felt that, since +we can't guarantee linear time complexity whenever the range to be +inserted is sorted, it's more trouble than it's worth to say that it's +linear in some special cases. +
+ + + + +Section: 20.2.3 [pairs] Status: WP + Submitter: Martin Sebor Date: 2000-09-11
+View all other issues in [pairs].
+View all issues with WP status.
+Discussion:
++I don't see any requirements on the types of the elements of the +std::pair container in 20.2.2. From the descriptions of the member +functions it appears that they must at least satisfy the requirements of +20.1.3 [lib.copyconstructible] and 20.1.4 [lib.default.con.req], and in +the case of the [in]equality operators also the requirements of 20.1.1 +[lib.equalitycomparable] and 20.1.2 [lib.lessthancomparable]. +
+ ++I believe that the the CopyConstructible requirement is unnecessary in +the case of 20.2.2, p2. +
+ + +Proposed resolution:
+Change the Effects clause in 20.2.2, p2 from
+ ++ ++-2- Effects: Initializes its members as if implemented: pair() : +first(T1()), second(T2()) {} +
to
+ ++ + ++-2- Effects: Initializes its members as if implemented: pair() : +first(), second() {} +
Rationale:
+The existing specification of pair's constructor appears to be a +historical artifact: there was concern that pair's members be properly +zero-initialized when they are built-in types. At one time there was +uncertainty about whether they would be zero-initialized if the +default constructor was written the obvious way. This has been +clarified by core issue 178, and there is no longer any doubt that +the straightforward implementation is correct.
+ + + + +Section: 18.7.2.1 [bad.exception] Status: WP + Submitter: Martin Sebor Date: 2000-09-24
+View all issues with WP status.
+Discussion:
++The synopsis for std::bad_exception lists the function ~bad_exception() +but there is no description of what the function does (the Effects +clause is missing). +
+ + +Proposed resolution:
++Remove the destructor from the class synopses of +bad_alloc (18.5.2.1 [bad.alloc]), +bad_cast (18.6.2 [bad.cast]), +bad_typeid (18.6.3 [bad.typeid]), +and bad_exception (18.7.2.1 [bad.exception]). +
+ + +Rationale:
++This is a general problem with the exception classes in clause 18. +The proposed resolution is to remove the destructors from the class +synopses, rather than to document the destructors' behavior, because +removing them is more consistent with how exception classes are +described in clause 19. +
+ + + + +Section: 22.1.1 [locale] Status: WP + Submitter: Martin Sebor Date: 2000-10-05
+View all other issues in [locale].
+View all issues with WP status.
+Discussion:
+The synopsis of the class std::locale in 22.1.1 contains two typos: +the semicolons after the declarations of the default ctor +locale::locale() and the copy ctor locale::locale(const locale&) +are missing.
+ + +Proposed resolution:
+Add the missing semicolons, i.e., change
+ +// construct/copy/destroy: + locale() throw() + locale(const locale& other) throw() ++ +
in the synopsis in 22.1.1 to
+ +// construct/copy/destroy: + locale() throw(); + locale(const locale& other) throw(); ++ + + + +
Section: 25.3.3 [alg.binary.search] Status: WP + Submitter: Matt Austern Date: 2000-10-18
+View all other issues in [alg.binary.search].
+View all issues with WP status.
+Duplicate of: 472
+Discussion:
++Each of the four binary search algorithms (lower_bound, upper_bound, +equal_range, binary_search) has a form that allows the user to pass a +comparison function object. According to 25.3, paragraph 2, that +comparison function object has to be a strict weak ordering. +
+ ++This requirement is slightly too strict. Suppose we are searching +through a sequence containing objects of type X, where X is some +large record with an integer key. We might reasonably want to look +up a record by key, in which case we would want to write something +like this: +
+struct key_comp { + bool operator()(const X& x, int n) const { + return x.key() < n; + } + } + + std::lower_bound(first, last, 47, key_comp()); ++ +
+key_comp is not a strict weak ordering, but there is no reason to +prohibit its use in lower_bound. +
+ ++There's no difficulty in implementing lower_bound so that it allows +the use of something like key_comp. (It will probably work unless an +implementor takes special pains to forbid it.) What's difficult is +formulating language in the standard to specify what kind of +comparison function is acceptable. We need a notion that's slightly +more general than that of a strict weak ordering, one that can encompass +a comparison function that involves different types. Expressing that +notion may be complicated. +
+ +Additional questions raised at the Toronto meeting:
+Additional discussion from Copenhagen:
+Proposed resolution:
+ +Change 25.3 [lib.alg.sorting] paragraph 3 from:
+ ++ ++ 3 For all algorithms that take Compare, there is a version that uses + operator< instead. That is, comp(*i, *j) != false defaults to *i < + *j != false. For the algorithms to work correctly, comp has to + induce a strict weak ordering on the values. +
to:
+ ++ ++ 3 For all algorithms that take Compare, there is a version that uses + operator< instead. That is, comp(*i, *j) != false defaults to *i + < *j != false. For algorithms other than those described in + lib.alg.binary.search (25.3.3) to work correctly, comp has to induce + a strict weak ordering on the values. +
Add the following paragraph after 25.3 [lib.alg.sorting] paragraph 5:
+ ++ ++ -6- A sequence [start, finish) is partitioned with respect to an + expression f(e) if there exists an integer n such that + for all 0 <= i < distance(start, finish), f(*(begin+i)) is true if + and only if i < n. +
Change 25.3.3 [lib.alg.binary.search] paragraph 1 from:
+ ++ ++ -1- All of the algorithms in this section are versions of binary + search and assume that the sequence being searched is in order + according to the implied or explicit comparison function. They work + on non-random access iterators minimizing the number of + comparisons, which will be logarithmic for all types of + iterators. They are especially appropriate for random access + iterators, because these algorithms do a logarithmic number of + steps through the data structure. For non-random access iterators + they execute a linear number of steps. +
to:
+ ++ ++ -1- All of the algorithms in this section are versions of binary + search and assume that the sequence being searched is partitioned + with respect to an expression formed by binding the search key to + an argument of the implied or explicit comparison function. They + work on non-random access iterators minimizing the number of + comparisons, which will be logarithmic for all types of + iterators. They are especially appropriate for random access + iterators, because these algorithms do a logarithmic number of + steps through the data structure. For non-random access iterators + they execute a linear number of steps. +
Change 25.3.3.1 [lib.lower.bound] paragraph 1 from:
+ ++ ++ -1- Requires: Type T is LessThanComparable + (lib.lessthancomparable). +
to:
+ ++ + ++ -1- Requires: The elements e of [first, last) are partitioned with + respect to the expression e < value or comp(e, value) +
Remove 25.3.3.1 [lib.lower.bound] paragraph 2:
+ ++ ++ -2- Effects: Finds the first position into which value can be + inserted without violating the ordering. +
Change 25.3.3.2 [lib.upper.bound] paragraph 1 from:
+ ++ ++ -1- Requires: Type T is LessThanComparable (lib.lessthancomparable). +
to:
+ ++ ++ -1- Requires: The elements e of [first, last) are partitioned with + respect to the expression !(value < e) or !comp(value, e) +
Remove 25.3.3.2 [lib.upper.bound] paragraph 2:
+ ++ ++ -2- Effects: Finds the furthermost position into which value can be + inserted without violating the ordering. +
Change 25.3.3.3 [lib.equal.range] paragraph 1 from:
+ ++ ++ -1- Requires: Type T is LessThanComparable + (lib.lessthancomparable). +
to:
+ ++ ++ -1- Requires: The elements e of [first, last) are partitioned with + respect to the expressions e < value and !(value < e) or + comp(e, value) and !comp(value, e). Also, for all elements e of + [first, last), e < value implies !(value < e) or comp(e, + value) implies !comp(value, e) +
Change 25.3.3.3 [lib.equal.range] paragraph 2 from:
+ ++ ++ -2- Effects: Finds the largest subrange [i, j) such that the value + can be inserted at any iterator k in it without violating the + ordering. k satisfies the corresponding conditions: !(*k < value) + && !(value < *k) or comp(*k, value) == false && comp(value, *k) == + false. +
to:
+ +-2- Returns: + make_pair(lower_bound(first, last, value), + upper_bound(first, last, value)) + or + make_pair(lower_bound(first, last, value, comp), + upper_bound(first, last, value, comp)) ++ +
Change 25.3.3.3 [lib.binary.search] paragraph 1 from:
+ ++ ++ -1- Requires: Type T is LessThanComparable + (lib.lessthancomparable). +
to:
+ ++ ++ -1- Requires: The elements e of [first, last) are partitioned with + respect to the expressions e < value and !(value < e) or comp(e, + value) and !comp(value, e). Also, for all elements e of [first, + last), e < value implies !(value < e) or comp(e, value) implies + !comp(value, e) +
[Copenhagen: Dave Abrahams provided this wording]
+ + +[Redmond: Minor changes in wording. (Removed "non-negative", and +changed the "other than those described in" wording.) Also, the LWG +decided to accept the "optional" part.]
+ + + + +Rationale:
+The proposed resolution reinterprets binary search. Instead of +thinking about searching for a value in a sorted range, we view that +as an important special case of a more general algorithm: searching +for the partition point in a partitioned range.
+ +We also add a guarantee that the old wording did not: we ensure +that the upper bound is no earlier than the lower bound, that +the pair returned by equal_range is a valid range, and that the first +part of that pair is the lower bound.
+ + + + + +Section: 27.6.1.5 [iostreamclass] Status: WP + Submitter: Martin Sebor Date: 2000-11-02
+View all issues with WP status.
+Discussion:
++Class template basic_iostream has no typedefs. The typedefs it +inherits from its base classes can't be used, since (for example) +basic_iostream<T>::traits_type is ambiguous. +
+ + +Proposed resolution:
+ +Add the following to basic_iostream's class synopsis in +27.6.1.5 [iostreamclass], immediately after public:
+ +// types: + typedef charT char_type; + typedef typename traits::int_type int_type; + typedef typename traits::pos_type pos_type; + typedef typename traits::off_type off_type; + typedef traits traits_type; ++ + + + +
Section: 27.4.4.3 [iostate.flags] Status: WP + Submitter: Martin Sebor Date: 2000-11-02
+View all other issues in [iostate.flags].
+View all issues with WP status.
+Duplicate of: 569
+Discussion:
++27.4.4.3, p4 says about the postcondition of the function: If +rdbuf()!=0 then state == rdstate(); otherwise +rdstate()==state|ios_base::badbit. +
+ ++The expression on the right-hand-side of the operator==() needs to be +parenthesized in order for the whole expression to ever evaluate to +anything but non-zero. +
+ + +Proposed resolution:
++Add parentheses like so: rdstate()==(state|ios_base::badbit). +
+ + + + +Section: 27 [input.output] Status: WP + Submitter: Martin Sebor Date: 2000-11-02
+View all other issues in [input.output].
+View all issues with WP status.
+Discussion:
+27.5.2.4.2, p4, and 27.8.1.6, p2, 27.8.1.7, p3, 27.8.1.9, p2, +27.8.1.10, p3 refer to in and/or out w/o ios_base:: qualification. +That's incorrect since the names are members of a dependent base +class (14.6.2 [temp.dep]) and thus not visible.
+ + +Proposed resolution:
+Qualify the names with the name of the class of which they are +members, i.e., ios_base.
+ + + + +Section: 20.1.2 [allocator.requirements] Status: WP + Submitter: Martin Sebor Date: 2000-11-02
+View other active issues in [allocator.requirements].
+View all other issues in [allocator.requirements].
+View all issues with WP status.
+Discussion:
++I see that table 31 in 20.1.5, p3 allows T in std::allocator<T> to be of +any type. But the synopsis in 20.4.1 calls for allocator<>::address() to +be overloaded on reference and const_reference, which is ill-formed for +all T = const U. In other words, this won't work: +
+ ++template class std::allocator<const int>; +
+ ++The obvious solution is to disallow specializations of allocators on +const types. However, while containers' elements are required to be +assignable (which rules out specializations on const T's), I think that +allocators might perhaps be potentially useful for const values in other +contexts. So if allocators are to allow const types a partial +specialization of std::allocator<const T> would probably have to be +provided. +
+ + +Proposed resolution:
+Change the text in row 1, column 2 of table 32 in 20.1.5, p3 from
+ ++ ++ any type +
to
++ ++ any non-const, non-reference type +
[Redmond: previous proposed resolution was "any non-const, +non-volatile, non-reference type". Got rid of the "non-volatile".]
+ + + + +Rationale:
++Two resolutions were originally proposed: one that partially +specialized std::allocator for const types, and one that said an +allocator's value type may not be const. The LWG chose the second. +The first wouldn't be appropriate, because allocators are intended for +use by containers, and const value types don't work in containers. +Encouraging the use of allocators with const value types would only +lead to unsafe code. +
++The original text for proposed resolution 2 was modified so that it +also forbids volatile types and reference types. +
+ +[Curaçao: LWG double checked and believes volatile is correctly +excluded from the PR.]
+ + + + + + + +Section: 22.2.2.1.1 [facet.num.get.members] Status: WP + Submitter: Matt Austern Date: 2000-11-02
+View all other issues in [facet.num.get.members].
+View all issues with WP status.
+Discussion:
++In 22.2.2.1.1, we have a list of overloads for num_get<>::get(). +There are eight overloads, all of which are identical except for the +last parameter. The overloads are: +
++There is a similar list, in 22.2.2.1.2, of overloads for +num_get<>::do_get(). In this list, the last parameter has +the types: +
++These two lists are not identical. They should be, since +get is supposed to call do_get with exactly +the arguments it was given. +
+ + +Proposed resolution:
+In 22.2.2.1.1 [facet.num.get.members], change
+iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, short& val) const; ++
to
+iter_type get(iter_type in, iter_type end, ios_base& str, + ios_base::iostate& err, float& val) const; ++ + + + +
Section: 23.1 [container.requirements] Status: WP + Submitter: Peter Dimov Date: 2000-11-07
+View other active issues in [container.requirements].
+View all other issues in [container.requirements].
+View all issues with WP status.
+Discussion:
++23.1/3 states that the objects stored in a container must be +Assignable. 23.3.1 [map], paragraph 2, +states that map satisfies all requirements for a container, while in +the same time defining value_type as pair<const Key, T> - a type +that is not Assignable. +
+ ++It should be noted that there exists a valid and non-contradictory +interpretation of the current text. The wording in 23.1/3 avoids +mentioning value_type, referring instead to "objects stored in a +container." One might argue that map does not store objects of +type map::value_type, but of map::mapped_type instead, and that the +Assignable requirement applies to map::mapped_type, not +map::value_type. +
+ ++However, this makes map a special case (other containers store objects of +type value_type) and the Assignable requirement is needlessly restrictive in +general. +
+ ++For example, the proposed resolution of active library issue +103 is to make set::iterator a constant iterator; this +means that no set operations can exploit the fact that the stored +objects are Assignable. +
+ ++This is related to, but slightly broader than, closed issue +140. +
+ + +Proposed resolution:
+23.1/3: Strike the trailing part of the sentence:
+++ , and the additional requirements of Assignable types from 23.1/3 +
so that it reads:
++ ++ -3- The type of objects stored in these components must meet the + requirements of CopyConstructible types (lib.copyconstructible). +
23.1/4: Modify to make clear that this requirement is not for all +containers. Change to:
+ ++ ++-4- Table 64 defines the Assignable requirement. Some containers +require this property of the types to be stored in the container. T is +the type used to instantiate the container. t is a value of T, and u is +a value of (possibly const) T. +
23.1, Table 65: in the first row, change "T is Assignable" to "T is +CopyConstructible".
+ +23.2.1/2: Add sentence for Assignable requirement. Change to:
+ ++ ++-2- A deque satisfies all of the requirements of a container and of a +reversible container (given in tables in lib.container.requirements) and +of a sequence, including the optional sequence requirements +(lib.sequence.reqmts). In addition to the requirements on the stored +object described in 23.1[lib.container.requirements], the stored object +must also meet the requirements of Assignable. Descriptions are +provided here only for operations on deque that are not described in one +of these tables or for operations where there is additional semantic +information. +
23.2.2/2: Add Assignable requirement to specific methods of list. +Change to:
+ +++ +-2- A list satisfies all of the requirements of a container and of a +reversible container (given in two tables in lib.container.requirements) +and of a sequence, including most of the the optional sequence +requirements (lib.sequence.reqmts). The exceptions are the operator[] +and at member functions, which are not provided. + +[Footnote: These member functions are only provided by containers whose +iterators are random access iterators. --- end foonote] +
+ +list does not require the stored type T to be Assignable unless the +following methods are instantiated: + +[Footnote: Implementors are permitted but not required to take advantage +of T's Assignable properties for these methods. -- end foonote] +
+list<T,Allocator>& operator=(const list<T,Allocator>& x ); + template <class InputIterator> + void assign(InputIterator first, InputIterator last); + void assign(size_type n, const T& t); ++ + +Descriptions are provided here only for operations on list that are not +described in one of these tables or for operations where there is +additional semantic information.
+
23.2.4/2: Add sentence for Assignable requirement. Change to:
+ ++ + ++-2- A vector satisfies all of the requirements of a container and of a +reversible container (given in two tables in lib.container.requirements) +and of a sequence, including most of the optional sequence requirements +(lib.sequence.reqmts). The exceptions are the push_front and pop_front +member functions, which are not provided. In addition to the +requirements on the stored object described in +23.1[lib.container.requirements], the stored object must also meet the +requirements of Assignable. Descriptions are provided here only for +operations on vector that are not described in one of these tables or +for operations where there is additional semantic information. +
Rationale:
+list, set, multiset, map, multimap are able to store non-Assignables. +However, there is some concern about list<T>: +although in general there's no reason for T to be Assignable, some +implementations of the member functions operator= and +assign do rely on that requirement. The LWG does not want +to forbid such implementations.
+ +Note that the type stored in a standard container must still satisfy +the requirements of the container's allocator; this rules out, for +example, such types as "const int". See issue 274 +for more details. +
+ +In principle we could also relax the "Assignable" requirement for +individual vector member functions, such as +push_back. However, the LWG did not see great value in such +selective relaxation. Doing so would remove implementors' freedom to +implement vector::push_back in terms of +vector::insert.
+ + + + + +Section: 23.2.4.4 [list.ops] Status: WP + Submitter: P.J. Plauger Date: 2000-11-27
+View all other issues in [list.ops].
+View all issues with WP status.
+Discussion:
++Section 23.2.4.4 [list.ops] states that +
+void splice(iterator position, list<T, Allocator>& x); ++
+invalidates all iterators and references to list x. +
+ ++But what does the C++ Standard mean by "invalidate"? You +can still dereference the iterator to a spliced list element, but +you'd better not use it to delimit a range within the original +list. For the latter operation, it has definitely lost some of its +validity. +
+ ++If we accept the proposed resolution to issue 250, +then we'd better clarify that a "valid" iterator need no +longer designate an element within the same container as it once did. +We then have to clarify what we mean by invalidating a past-the-end +iterator, as when a vector or string grows by reallocation. Clearly, +such an iterator has a different kind of validity. Perhaps we should +introduce separate terms for the two kinds of "validity." +
+ + +Proposed resolution:
+Add the following text to the end of section 24.1 [iterator.requirements], +after paragraph 5:
++ ++An invalid iterator is an iterator that may be +singular. [Footnote: This definition applies to pointers, since +pointers are iterators. The effect of dereferencing an iterator that +has been invalidated is undefined.] +
[post-Copenhagen: Matt provided wording.]
+ + +[Redmond: General agreement with the intent, some objections to +the wording. Dave provided new wording.]
+ + + +Rationale:
+This resolution simply defines a term that the Standard uses but + never defines, "invalid", in terms of a term that is defined, + "singular".
+ +Why do we say "may be singular", instead of "is singular"? That's + becuase a valid iterator is one that is known to be nonsingular. + Invalidating an iterator means changing it in such a way that it's + no longer known to be nonsingular. An example: inserting an + element into the middle of a vector is correctly said to invalidate + all iterators pointing into the vector. That doesn't necessarily + mean they all become singular.
+ + + + + +Section: 24.4.1 [reverse.iterators] Status: WP + Submitter: Steve Cleary Date: 2000-11-27
+View all issues with WP status.
+Discussion:
++This came from an email from Steve Cleary to Fergus in reference to +issue 179. The library working group briefly discussed +this in Toronto and believed it should be a separate issue. There was +also some reservations about whether this was a worthwhile problem to +fix. +
+ ++Steve said: "Fixing reverse_iterator. std::reverse_iterator can +(and should) be changed to preserve these additional +requirements." He also said in email that it can be done without +breaking user's code: "If you take a look at my suggested +solution, reverse_iterator doesn't have to take two parameters; there +is no danger of breaking existing code, except someone taking the +address of one of the reverse_iterator global operator functions, and +I have to doubt if anyone has ever done that. . . But, just in +case they have, you can leave the old global functions in as well -- +they won't interfere with the two-template-argument functions. With +that, I don't see how any user code could break." +
+ + +Proposed resolution:
++Section: 24.4.1.1 [reverse.iterator] +add/change the following declarations:
+A) Add a templated assignment operator, after the same manner + as the templated copy constructor, i.e.: + + template < class U > + reverse_iterator < Iterator >& operator=(const reverse_iterator< U >& u); + + B) Make all global functions (except the operator+) have + two template parameters instead of one, that is, for + operator ==, !=, <, >, <=, >=, - replace: + + template < class Iterator > + typename reverse_iterator< Iterator >::difference_type operator-( + const reverse_iterator< Iterator >& x, + const reverse_iterator< Iterator >& y); + + with: + + template < class Iterator1, class Iterator2 > + typename reverse_iterator < Iterator1 >::difference_type operator-( + const reverse_iterator < Iterator1 > & x, + const reverse_iterator < Iterator2 > & y); ++
+Also make the addition/changes for these signatures in +24.4.1.3 [reverse.iter.ops]. +
+ +[ +Copenhagen: The LWG is concerned that the proposed resolution +introduces new overloads. Experience shows that introducing +overloads is always risky, and that it would be inappropriate to +make this change without implementation experience. It may be +desirable to provide this feature in a different way. +]
+ + +[ +Lillehammer: We now have implementation experience, and agree that +this solution is safe and correct. +]
+ + + + + + + +Section: 25.3.7 [alg.min.max] Status: WP + Submitter: Martin Sebor Date: 2000-12-02
+View all other issues in [alg.min.max].
+View all issues with WP status.
+Duplicate of: 486
+Discussion:
+The requirements in 25.3.7, p1 and 4 call for T to satisfy the +requirements of LessThanComparable ( [lessthancomparable]) +and CopyConstructible (20.1.1 [utility.arg.requirements]). +Since the functions take and return their arguments and result by +const reference, I believe the CopyConstructible requirement +is unnecessary. +
+ + +Proposed resolution:
+Remove the CopyConstructible requirement. Specifically, replace +25.3.7, p1 with
+-1- Requires: Type T is LessThanComparable +( [lessthancomparable]). +
+and replace 25.3.7, p4 with
+-4- Requires: Type T is LessThanComparable +( [lessthancomparable]). +
+ + + + +Section: 22.2.2.2.2 [facet.num.put.virtuals] Status: WP + Submitter: Howard Hinnant Date: 2000-12-05
+View all other issues in [facet.num.put.virtuals].
+View all issues with WP status.
+Discussion:
++Paragraph 16 mistakenly singles out integral types for inserting +thousands_sep() characters. This conflicts with the syntax for floating +point numbers described under 22.2.3.1/2. +
+ + +Proposed resolution:
+Change paragraph 16 from:
+ ++ ++For integral types, punct.thousands_sep() characters are inserted into +the sequence as determined by the value returned by punct.do_grouping() +using the method described in 22.2.3.1.2 [facet.numpunct.virtuals]. +
To:
+ ++ ++For arithmetic types, punct.thousands_sep() characters are inserted into +the sequence as determined by the value returned by punct.do_grouping() +using the method described in 22.2.3.1.2 [facet.numpunct.virtuals]. +
[ +Copenhagen: Opinions were divided about whether this is actually an +inconsistency, but at best it seems to have been unintentional. This +is only an issue for floating-point output: The standard is +unambiguous that implementations must parse thousands_sep characters +when performing floating-point. The standard is also unambiguous that +this requirement does not apply to the "C" locale. +]
+ + +[ +A survey of existing practice is needed; it is believed that some +implementations do insert thousands_sep characters for floating-point +output and others fail to insert thousands_sep characters for +floating-point input even though this is unambiguously required by the +standard. +]
+ + +[Post-Curaçao: the above proposed resolution is the consensus of +Howard, Bill, Pete, Benjamin, Nathan, Dietmar, Boris, and Martin.]
+ + + + + + +Section: 25.2.5 [alg.replace] Status: WP + Submitter: Martin Sebor Date: 2000-12-15
+View all other issues in [alg.replace].
+View all issues with WP status.
+Duplicate of: 483
+Discussion:
++(revision of the further discussion) +There are a number of problems with the requires clauses for the +algorithms in 25.1 and 25.2. The requires clause of each algorithm +should describe the necessary and sufficient requirements on the inputs +to the algorithm such that the algorithm compiles and runs properly. +Many of the requires clauses fail to do this. Here is a summary of the kinds +of mistakes: +
+ ++Here is the list of algorithms that contain mistakes: +
+ ++Also, in the requirements for EqualityComparable, the requirement that +the operator be defined for const objects is lacking. +
+ + + +Proposed resolution:
+ +20.1.1 Change p1 from
+ +In Table 28, T is a type to be supplied by a C++ program +instantiating a template, a, b, and c are +values of type T. +
+ +to
+ ++In Table 28, T is a type to be supplied by a C++ program +instantiating a template, a, b, and c are +values of type const T. +
+ +25 Between p8 and p9
+ +Add the following sentence:
+ +When the description of an algorithm gives an expression such as +*first == value for a condition, it is required that the expression +evaluate to either true or false in boolean contexts.
+ +25.1.2 Change p1 by deleting the requires clause.
+ +25.1.6 Change p1 by deleting the requires clause.
+ +25.1.9
+ +Change p4 from
+ +-4- Requires: Type T is EqualityComparable +(20.1.1), type Size is convertible to integral type (4.7.12.3). +
+ +to
+ +-4- Requires: The type Size is convertible to integral +type (4.7.12.3).
+ +25.2.4 Change p1 from
+ +-1- Requires: Type T is Assignable (23.1 ) (and, for replace(), EqualityComparable (20.1.1 )).
+ +to
+ +-1- Requires: The expression *first = new_value must be valid.
+ +and change p4 from
+ +-4- Requires: Type T is Assignable (23.1) (and, +for replace_copy(), EqualityComparable +(20.1.1)). The ranges [first, last) and [result, result + +(last - first)) shall not overlap.
+ +to
+ +-4- Requires: The results of the expressions *first and +new_value must be writable to the result output iterator. The +ranges [first, last) and [result, result + (last - +first)) shall not overlap.
+ + +25.2.5 Change p1 from
+ +-1- Requires: Type T is Assignable (23.1). The +type Size is convertible to an integral type (4.7.12.3).
+ +to
+ +-1- Requires: The expression value must be is writable to +the output iterator. The type Size is convertible to an +integral type (4.7.12.3).
+ +25.2.7 Change p1 from
+ +-1- Requires: Type T is EqualityComparable (20.1.1).
+ +to
+ ++-1- Requires: The value type of the iterator must be +Assignable (23.1). +
+ + + +Rationale:
++The general idea of the proposed solution is to remove the faulty +requires clauses and let the returns and effects clauses speak for +themselves. That is, the returns clauses contain expressions that must +be valid, and therefore already imply the correct requirements. In +addition, a sentence is added at the beginning of chapter 25 saying +that expressions given as conditions must evaluate to true or false in +a boolean context. An alternative would be to say that the type of +these condition expressions must be literally bool, but that would be +imposing a greater restriction that what the standard currently says +(which is convertible to bool). +
+ + + + + +Section: 20.6.7 [comparisons] Status: WP + Submitter: Martin Sebor Date: 2000-12-26
+View all issues with WP status.
+Discussion:
+The example in 20.6.7 [comparisons], p6 shows how to use the C +library function strcmp() with the function pointer adapter +ptr_fun(). But since it's unspecified whether the C library +functions have extern "C" or extern +"C++" linkage [17.4.2.2 [using.linkage]], and since +function pointers with different the language linkage specifications +(7.5 [dcl.link]) are incompatible, whether this example is +well-formed is unspecified. +
+ + +Proposed resolution:
+Change 20.6.7 [comparisons] paragraph 6 from:
+++ + +[Example:
+replace_if(v.begin(), v.end(), not1(bind2nd(ptr_fun(strcmp), "C")), "C++"); ++replaces each C with C++ in sequence v.
+
to:
+++ +[Example:
+int compare(const char*, const char*); + replace_if(v.begin(), v.end(), + not1(bind2nd(ptr_fun(compare), "abc")), "def"); ++replaces each abc with def in sequence v.
+
Also, remove footnote 215 in that same paragraph.
+ +[Copenhagen: Minor change in the proposed resolution. Since this +issue deals in part with C and C++ linkage, it was believed to be too +confusing for the strings in the example to be "C" and "C++". +]
+ + +[Redmond: More minor changes. Got rid of the footnote (which +seems to make a sweeping normative requirement, even though footnotes +aren't normative), and changed the sentence after the footnote so that +it corresponds to the new code fragment.]
+ + + + + + +Section: 27.8.1.7 [ifstream.cons] Status: WP + Submitter: Martin Sebor Date: 2000-12-31
+View all issues with WP status.
+Discussion:
+27.8.1.7 [ifstream.cons], p2, 27.8.1.11 [ofstream.cons], p2, and +27.8.1.15 [fstream.cons], p2 say about the effects of each constructor: +
+ +... If that function returns a null pointer, calls +setstate(failbit) (which may throw ios_base::failure). +
+ +The parenthetical note doesn't apply since the ctors cannot throw an +exception due to the requirement in 27.4.4.1 [basic.ios.cons], p3 +that exceptions() be initialized to ios_base::goodbit. +
+ + +Proposed resolution:
++Strike the parenthetical note from the Effects clause in each of the +paragraphs mentioned above. +
+ + + + +Section: 25.4 [alg.c.library] Status: WP + Submitter: Judy Ward Date: 2000-12-30
+View all other issues in [alg.c.library].
+View all issues with WP status.
+Discussion:
++The <cstdlib> header file contains prototypes for bsearch and +qsort (C++ Standard section 25.4 paragraphs 3 and 4) and other +prototypes (C++ Standard section 21.4 paragraph 1 table 49) that +require the typedef size_t. Yet size_t is not listed in the +<cstdlib> synopsis table 78 in section 25.4. +
+ + +Proposed resolution:
++Add the type size_t to Table 78 (section 25.4) and add +the type size_t <cstdlib> to Table 97 (section C.2). +
+ + +Rationale:
+Since size_t is in <stdlib.h>, it must also be in <cstdlib>.
+ + + + + +Section: 19.3 [errno] Status: WP + Submitter: Judy Ward Date: 2000-12-30
+View all issues with WP status.
+Discussion:
++ISO/IEC 9899:1990/Amendment1:1994 Section 4.3 States: "The list +of macros defined in <errno.h> is adjusted to include a new +macro, EILSEQ" +
+ ++ISO/IEC 14882:1998(E) section 19.3 does not refer +to the above amendment. +
+ + + +Proposed resolution:
++Update Table 26 (section 19.3) "Header <cerrno> synopsis" +and Table 95 (section C.2) "Standard Macros" to include EILSEQ. +
+ + + + + +Section: 25.3.5 [alg.set.operations] Status: WP + Submitter: Matt Austern Date: 2001-01-03
+View all other issues in [alg.set.operations].
+View all issues with WP status.
+Discussion:
++The standard library contains four algorithms that compute set +operations on sorted ranges: set_union, set_intersection, +set_difference, and set_symmetric_difference. Each +of these algorithms takes two sorted ranges as inputs, and writes the +output of the appropriate set operation to an output range. The elements +in the output range are sorted. +
+ ++The ordinary mathematical definitions are generalized so that they +apply to ranges containing multiple copies of a given element. Two +elements are considered to be "the same" if, according to an +ordering relation provided by the user, neither one is less than the +other. So, for example, if one input range contains five copies of an +element and another contains three, the output range of set_union +will contain five copies, the output range of +set_intersection will contain three, the output range of +set_difference will contain two, and the output range of +set_symmetric_difference will contain two. +
+ ++Because two elements can be "the same" for the purposes +of these set algorithms, without being identical in other respects +(consider, for example, strings under case-insensitive comparison), +this raises a number of unanswered questions: +
+ ++The standard should either answer these questions, or explicitly +say that the answers are unspecified. I prefer the former option, +since, as far as I know, all existing implementations behave the +same way. +
+ + + +Proposed resolution:
+ +Add the following to the end of 25.3.5.2 [set.union] paragraph 5:
++ ++If [first1, last1) contains m elements that are equivalent to +each other and [first2, last2) contains n elements that are +equivalent to them, then max(m, n) of these elements +will be copied to the output range: all m of these elements +from [first1, last1), and the last max(n-m, 0) of them from +[first2, last2), in that order. +
Add the following to the end of 25.3.5.3 [set.intersection] paragraph 5:
++ ++If [first1, last1) contains m elements that are equivalent to each +other and [first2, last2) contains n elements that are +equivalent to them, the first min(m, n) of those +elements from [first1, last1) are copied to the output range. +
Add a new paragraph, Notes, after 25.3.5.4 [set.difference] +paragraph 4:
++ ++If [first1, last1) contains m elements that are equivalent to each +other and [first2, last2) contains n elements that are +equivalent to them, the last max(m-n, 0) elements from +[first1, last1) are copied to the output range. +
Add a new paragraph, Notes, after 25.3.5.5 [set.symmetric.difference] +paragraph 4:
++ ++If [first1, last1) contains m elements that are equivalent to +each other and [first2, last2) contains n elements that are +equivalent to them, then |m - n| of those elements will be +copied to the output range: the last m - n of these elements +from [first1, last1) if m > n, and the last n - +m of these elements from [first2, last2) if m < n. +
[Santa Cruz: it's believed that this language is clearer than + what's in the Standard. However, it's also believed that the + Standard may already make these guarantees (although not quite in + these words). Bill and Howard will check and see whether they think + that some or all of these changes may be redundant. If so, we may + close this issue as NAD.]
+ + + + +Rationale:
+For simple cases, these descriptions are equivalent to what's + already in the Standard. For more complicated cases, they describe + the behavior of existing implementations.
+ + + + + +Section: 27.4.4.2 [basic.ios.members] Status: WP + Submitter: Martin Sebor Date: 2001-01-05
+View other active issues in [basic.ios.members].
+View all other issues in [basic.ios.members].
+View all issues with WP status.
+Discussion:
+The Effects clause of the member function copyfmt() in +27.4.4.2, p15 doesn't consider the case where the left-hand side +argument is identical to the argument on the right-hand side, that is +(this == &rhs). If the two arguments are identical there +is no need to copy any of the data members or call any callbacks +registered with register_callback(). Also, as Howard Hinnant +points out in message c++std-lib-8149 it appears to be incorrect to +allow the object to fire erase_event followed by +copyfmt_event since the callback handling the latter event +may inadvertently attempt to access memory freed by the former. +
+ + +Proposed resolution:
+Change the Effects clause in 27.4.4.2, p15 from
+ ++ ++-15- Effects:Assigns to the member objects of *this +the corresponding member objects of rhs, except that... +
to
+ ++ + + + ++-15- Effects:If (this == &rhs) does nothing. Otherwise +assigns to the member objects of *this the corresponding member +objects of rhs, except that... +
Section: 17.4.3.2.1 [macro.names] Status: WP + Submitter: James Kanze Date: 2001-01-11
+View all issues with WP status.
+Discussion:
+Paragraph 2 of 17.4.3.2.1 [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 +would mean that the following program is legal:
+ +#define npos 3.14 + #include <sstream> ++ +
since npos is not defined in <sstream>. It is, however, defined +in <string>, and it is hard to imagine an implementation in +which <sstream> didn't include <string>.
+ +I think that this phrase was probably formulated before it was +decided that a standard header may freely include other standard +headers. The phrase would be perfectly appropriate for C, for +example. In light of 17.4.4.1 [res.on.headers] paragraph 1, however, +it isn't stringent enough.
+ + +Proposed resolution:
+For 17.4.3.2.1 [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)
+ +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: 26.7 [c.math] Status: WP + Submitter: Jens Maurer Date: 2001-01-12
+View all other issues in [c.math].
+View all issues with WP status.
+Discussion:
++Table 80 lists the contents of the <cmath> header. It does not +list abs(). However, 26.5, paragraph 6, which lists added +signatures present in <cmath>, does say that several overloads +of abs() should be defined in <cmath>. +
+ + +Proposed resolution:
++Add abs to Table 80. Also, remove the parenthetical list +of functions "(abs(), div(), rand(), srand())" from 26.5 [numarray], +paragraph 1. +
+ +[Copenhagen: Modified proposed resolution so that it also gets +rid of that vestigial list of functions in paragraph 1.]
+ + + + +Rationale:
+All this DR does is fix a typo; it's uncontroversial. A +separate question is whether we're doing the right thing in +putting some overloads in <cmath> that we aren't also +putting in <cstdlib>. That's issue 323.
+ + + + + +Section: 20.6.8 [logical.operations] Status: WP + Submitter: Martin Sebor Date: 2001-01-06
+View all issues with WP status.
+Discussion:
+The class templates const_mem_fun_t in 20.5.8, p8 and +const_mem_fun1_t +in 20.5.8, p9 derive from unary_function<T*, S>, and +binary_function<T*, +A, S>, respectively. Consequently, their argument_type, and +first_argument_type +members, respectively, are both defined to be T* (non-const). +However, their function call member operator takes a const T* +argument. It is my opinion that argument_type should be const +T* instead, so that one can easily refer to it in generic code. The +example below derived from existing code fails to compile due to the +discrepancy: +
+ +template <class T>
+
void foo (typename T::argument_type arg) // #1
+
{
+
typename T::result_type (T::*pf) (typename
+T::argument_type)
+const = // #2
+
&T::operator();
+
}
+
struct X { /* ... */ };
+ +int main ()
+
{
+
const X x;
+
foo<std::const_mem_fun_t<void, X>
+>(&x);
+// #3
+
}
+
#1 foo() takes a plain unqualified X* as an argument
+
#2 the type of the pointer is incompatible with the type of the member
+function
+
#3 the address of a constant being passed to a function taking a non-const
+X*
+
Proposed resolution:
+Replace the top portion of the definition of the class template +const_mem_fun_t in 20.5.8, p8 +
+template <class S, class T> class const_mem_fun_t
+
: public
+unary_function<T*, S> {
+
with
+template <class S, class T> class const_mem_fun_t
+
: public
+unary_function<const T*, S> {
+
Also replace the top portion of the definition of the class template +const_mem_fun1_t in 20.5.8, p9
+template <class S, class T, class A> class const_mem_fun1_t
+
: public
+binary_function<T*, A, S> {
+
with
+template <class S, class T, class A> class const_mem_fun1_t
+
: public
+binary_function<const T*, A, S> {
+
Rationale:
+This is simply a contradiction: the argument_type typedef, +and the argument type itself, are not the same.
+ + + + + +Section: 18.5.1.2 [new.delete.array] Status: WP + Submitter: John A. Pedretti Date: 2001-01-10
+View all issues with WP status.
+Discussion:
++The default behavior of operator delete[] described in 18.5.1.2, p12 - +namely that for non-null value of ptr, the operator reclaims storage +allocated by the earlier call to the default operator new[] - is not +correct in all cases. Since the specified operator new[] default +behavior is to call operator new (18.5.1.2, p4, p8), which can be +replaced, along with operator delete, by the user, to implement their +own memory management, the specified default behavior of operator +delete[] must be to call operator delete. +
+ + +Proposed resolution:
+Change 18.5.1.2, p12 from
++ ++-12- Default behavior:
++
+- +For a null value of ptr , does nothing. +
+- +Any other value of ptr shall be a value returned +earlier by a call to the default operator new[](std::size_t). +[Footnote: The value must not have been invalidated by an intervening +call to operator delete[](void*) (17.4.3.8 [res.on.arguments]). +--- end footnote] +For such a non-null value of ptr , reclaims storage +allocated by the earlier call to the default operator new[]. +
+
to
+ +++-12- Default behavior: Calls operator +delete(ptr) +or operator delete(ptr, std::nothrow) respectively. +
and expunge paragraph 13.
+ + + + +Section: 23.2.4.4 [list.ops] Status: WP + Submitter: John Pedretti Date: 2001-01-23
+View all other issues in [list.ops].
+View all issues with WP status.
+Discussion:
++The "Effects" clause for list::merge() (23.2.4.4 [list.ops], p23) +appears to be incomplete: it doesn't cover the case where the argument +list is identical to *this (i.e., this == &x). The requirement in the +note in p24 (below) is that x be empty after the merge which is surely +unintended in this case. +
+ + +Proposed resolution:
+In 23.2.4.4 [list.ops], replace paragraps 23-25 with:
+++ ++23 Effects: if (&x == this) does nothing; otherwise, merges the two +sorted ranges [begin(), end()) and [x.begin(), x.end()). The result +is a range in which the elements will be sorted in non-decreasing +order according to the ordering defined by comp; that is, for every +iterator i in the range other than the first, the condition comp(*i, +*(i - 1)) will be false. +
+ ++24 Notes: Stable: if (&x != this), then for equivalent elements in the +two original ranges, the elements from the original range [begin(), +end()) always precede the elements from the original range [x.begin(), +x.end()). If (&x != this) the range [x.begin(), x.end()) is empty +after the merge. +
+ ++25 Complexity: At most size() + x.size() - 1 applications of comp if +(&x ! = this); otherwise, no applications of comp are performed. If +an exception is thrown other than by a comparison there are no +effects. +
+ +
[Copenhagen: The original proposed resolution did not fix all of +the problems in 23.2.4.4 [list.ops], p22-25. Three different +paragraphs (23, 24, 25) describe the effects of merge. +Changing p23, without changing the other two, appears to introduce +contradictions. Additionally, "merges the argument list into the +list" is excessively vague.]
+ + +[Post-Curaçao: Robert Klarer provided new wording.]
+ + + + + + + +Section: 21.3.1 [string.require] Status: WP + Submitter: Martin Sebor Date: 2001-01-27
+View all other issues in [string.require].
+View all issues with WP status.
+Discussion:
++The effects clause for the basic_string template ctor in 21.3.1, p15 +leaves out the third argument of type Allocator. I believe this to be +a mistake. +
+ + +Proposed resolution:
+Replace
+ +++ +-15- Effects: If InputIterator is an integral + type, equivalent to
+ ++basic_string(static_cast<size_type>(begin), + static_cast<value_type>(end))
with
+ +++ + + + +-15- Effects: If InputIterator is an integral + type, equivalent to
+ ++basic_string(static_cast<size_type>(begin), + static_cast<value_type>(end), a)
Section: 23.3.5.3 [bitset.operators] Status: WP + Submitter: Matt Austern Date: 2001-02-05
+View all issues with WP status.
+Discussion:
++In 23.3.5.3, we are told that bitset's input operator +"Extracts up to N (single-byte) characters from +is.", where is is a stream of type +basic_istream<charT, traits>. +
+ ++The standard does not say what it means to extract single byte +characters from a stream whose character type, charT, is in +general not a single-byte character type. Existing implementations +differ. +
+ ++A reasonable solution will probably involve widen() and/or +narrow(), since they are the supplied mechanism for +converting a single character between char and +arbitrary charT. +
+ +Narrowing the input characters is not the same as widening the +literals '0' and '1', because there may be some +locales in which more than one wide character maps to the narrow +character '0'. Narrowing means that alternate +representations may be used for bitset input, widening means that +they may not be.
+ +Note that for numeric input, num_get<> +(22.2.2.1.2/8) compares input characters to widened version of narrow +character literals.
+ +From Pete Becker, in c++std-lib-8224:
+++ ++Different writing systems can have different representations for the +digits that represent 0 and 1. For example, in the Unicode representation +of the Devanagari script (used in many of the Indic languages) the digit 0 +is 0x0966, and the digit 1 is 0x0967. Calling narrow would translate those +into '0' and '1'. But Unicode also provides the ASCII values 0x0030 and +0x0031 for for the Latin representations of '0' and '1', as well as code +points for the same numeric values in several other scripts (Tamil has no +character for 0, but does have the digits 1-9), and any of these values +would also be narrowed to '0' and '1'. +
+ +...
+ ++It's fairly common to intermix both native and Latin +representations of numbers in a document. So I think the rule has to be +that if a wide character represents a digit whose value is 0 then the bit +should be cleared; if it represents a digit whose value is 1 then the bit +should be set; otherwise throw an exception. So in a Devanagari locale, +both 0x0966 and 0x0030 would clear the bit, and both 0x0967 and 0x0031 +would set it. Widen can't do that. It would pick one of those two values, +and exclude the other one. +
+ +
From Jens Maurer, in c++std-lib-8233:
+ +++ + + ++Whatever we decide, I would find it most surprising if +bitset conversion worked differently from int conversion +with regard to alternate local representations of +numbers. +
+ +Thus, I think the options are:
++
+- Have a new defect issue for 22.2.2.1.2/8 so that it will +require the use of narrow().
+ +- Have a defect issue for bitset() which describes clearly +that widen() is to be used.
+
Proposed resolution:
+ +Replace the first two sentences of paragraph 5 with:
+ ++ ++ Extracts up to N characters from is. Stores these + characters in a temporary object str of type + basic_string<charT, traits>, then evaluates the + expression x = bitset<N>(str). +
Replace the third bullet item in paragraph 5 with:
+Rationale:
+Input for bitset should work the same way as numeric +input. Using widen does mean that alternative digit +representations will not be recognized, but this was a known +consequence of the design choice.
+ + + + + +Section: 22.2.1.5 [locale.codecvt.byname] Status: WP + Submitter: Howard Hinnant Date: 2001-01-24
+View all other issues in [locale.codecvt.byname].
+View all issues with WP status.
+Discussion:
+22.2.1.5/3 introduces codecvt in part with:
+ ++ ++ codecvt<wchar_t,char,mbstate_t> converts between the native + character sets for tiny and wide characters. Instantiations on + mbstate_t perform conversion between encodings known to the library + implementor. +
But 22.2.1.5.2/10 describes do_length in part with:
+ ++ ++ ... codecvt<wchar_t, char, mbstate_t> ... return(s) the lesser of max and + (from_end-from). +
+The semantics of do_in and do_length are linked. What one does must +be consistent with what the other does. 22.2.1.5/3 leads me to +believe that the vendor is allowed to choose the algorithm that +codecvt<wchar_t,char,mbstate_t>::do_in performs so that it makes +his customers happy on a given platform. But 22.2.1.5.2/10 explicitly +says what codecvt<wchar_t,char,mbstate_t>::do_length must +return. And thus indirectly specifies the algorithm that +codecvt<wchar_t,char,mbstate_t>::do_in must perform. I believe +that this is not what was intended and is a defect. +
+ +Discussion from the -lib reflector:
+
+
This proposal would have the effect of making the semantics of
+all of the virtual functions in codecvt<wchar_t, char,
+mbstate_t> implementation specified. Is that what we want, or
+do we want to mandate specific behavior for the base class virtuals
+and leave the implementation specified behavior for the codecvt_byname
+derived class? The tradeoff is that former allows implementors to
+write a base class that actually does something useful, while the
+latter gives users a way to get known and specified---albeit
+useless---behavior, and is consistent with the way the standard
+handles other facets. It is not clear what the original intention
+was.
+Nathan has suggest a compromise: a character that is a widened version +of the characters in the basic execution character set must be +converted to a one-byte sequence, but there is no such requirement +for characters that are not part of the basic execution character set. +
+ + +Proposed resolution:
++Change 22.2.1.5.2/5 from: +
++The instantiations required in Table 51 (lib.locale.category), namely +codecvt<wchar_t,char,mbstate_t> and +codecvt<char,char,mbstate_t>, store no characters. Stores no more +than (to_limit-to) destination elements. It always leaves the to_next +pointer pointing one beyond the last element successfully stored. +
++to: +
++Stores no more than (to_limit-to) destination elements, and leaves the +to_next pointer pointing one beyond the last element successfully +stored. codecvt<char,char,mbstate_t> stores no characters. +
+ +Change 22.2.1.5.2/10 from:
+ ++ ++-10- Returns: (from_next-from) where from_next is the largest value in +the range [from,from_end] such that the sequence of values in the +range [from,from_next) represents max or fewer valid complete +characters of type internT. The instantiations required in Table 51 +(21.1.1.1.1), namely codecvt<wchar_t, char, mbstate_t> and +codecvt<char, char, mbstate_t>, return the lesser of max and +(from_end-from). +
to:
+ ++ ++-10- Returns: (from_next-from) where from_next is the largest value in +the range [from,from_end] such that the sequence of values in the range +[from,from_next) represents max or fewer valid complete characters of +type internT. The instantiation codecvt<char, char, mbstate_t> returns +the lesser of max and (from_end-from). +
[Redmond: Nathan suggested an alternative resolution: same as +above, but require that, in the default encoding, a character from the +basic execution character set would map to a single external +character. The straw poll was 8-1 in favor of the proposed +resolution.]
+ + + + +Rationale:
+The default encoding should be whatever users of a given platform +would expect to be the most natural. This varies from platform to +platform. In many cases there is a preexisting C library, and users +would expect the default encoding to be whatever C uses in the default +"C" locale. We could impose a guarantee like the one Nathan suggested +(a character from the basic execution character set must map to a +single external character), but this would rule out important +encodings that are in common use: it would rule out JIS, for +example, and it would rule out a fixed-width encoding of UCS-4.
+ +[Curaçao: fixed rationale typo at the request of Ichiro Koshida; +"shift-JIS" changed to "JIS".]
+ + + + + + + +Section: 18.1 [support.types] Status: WP + Submitter: Steve Clamage Date: 2001-02-21
+View all other issues in [support.types].
+View all issues with WP status.
+Discussion:
+Spliced together from reflector messages c++std-lib-8294 and -8295:
+ +18.1, paragraph 5, reads: "The macro offsetof +accepts a restricted set of type arguments in this +International Standard. type shall be a POD structure or a POD +union (clause 9). The result of applying the offsetof macro to a field +that is a static data member or a function member is +undefined."
+ +For the POD requirement, it doesn't say "no diagnostic +required" or "undefined behavior". I read 1.4 [intro.compliance], paragraph 1, to mean that a diagnostic is required. +It's not clear whether this requirement was intended. While it's +possible to provide such a diagnostic, the extra complication doesn't +seem to add any value. +
+ + +Proposed resolution:
+Change 18.1, paragraph 5, to "If type is not a POD +structure or a POD union the results are undefined."
+ +[Copenhagen: straw poll was 7-4 in favor. It was generally +agreed that requiring a diagnostic was inadvertent, but some LWG +members thought that diagnostics should be required whenever +possible.]
+ + + + + + +Section: 23.2.4 [list] Status: WP + Submitter: Howard Hinnant Date: 2001-03-13
+View all issues with WP status.
+Discussion:
+ +From reflector message c++std-lib-8330. See also lib-8317.
+ ++The standard is currently inconsistent in 23.2.4.2 [list.capacity] +paragraph 1 and 23.2.4.3 [list.modifiers] paragraph 1. +23.2.3.3/1, for example, says: +
+ ++ ++-1- Any sequence supporting operations back(), push_back() and pop_back() +can be used to instantiate stack. In particular, vector (lib.vector), list +(lib.list) and deque (lib.deque) can be used. +
But this is false: vector<bool> can not be used, because the +container adaptors return a T& rather than using the underlying +container's reference type.
+ +This is a contradiction that can be fixed by:
+ ++I propose 3. This does not preclude option 2 if we choose to do it +later (see issue 96); the issues are independent. Option +3 offers a small step towards support for proxied containers. This +small step fixes a current contradiction, is easy for vendors to +implement, is already implemented in at least one popular lib, and +does not break any code. +
+ + + +Proposed resolution:
+Summary: Add reference and const_reference typedefs to queue, +priority_queue and stack. Change return types of "value_type&" to +"reference". Change return types of "const value_type&" to +"const_reference". Details:
+ +Change 23.2.3.1/1 from:
+ +namespace std { + template <class T, class Container = deque<T> > + class queue { + public: + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef Container container_type; + protected: + Container c; + + public: + explicit queue(const Container& = Container()); + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + value_type& front() { return c.front(); } + const value_type& front() const { return c.front(); } + value_type& back() { return c.back(); } + const value_type& back() const { return c.back(); } + void push(const value_type& x) { c.push_back(x); } + void pop() { c.pop_front(); } + }; ++ +
to:
+ +namespace std { + template <class T, class Container = deque<T> > + class queue { + public: + typedef typename Container::value_type value_type; + typedef typename Container::reference reference; + typedef typename Container::const_reference const_reference; + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef Container container_type; + protected: + Container c; + + public: + explicit queue(const Container& = Container()); + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + reference front() { return c.front(); } + const_reference front() const { return c.front(); } + reference back() { return c.back(); } + const_reference back() const { return c.back(); } + void push(const value_type& x) { c.push_back(x); } + void pop() { c.pop_front(); } + }; ++ +
Change 23.2.3.2/1 from:
+ +namespace std { + template <class T, class Container = vector<T>, + class Compare = less<typename Container::value_type> > + class priority_queue { + public: + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef Container container_type; + protected: + Container c; + Compare comp; + + public: + explicit priority_queue(const Compare& x = Compare(), + const Container& = Container()); + template <class InputIterator> + priority_queue(InputIterator first, InputIterator last, + const Compare& x = Compare(), + const Container& = Container()); + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + const value_type& top() const { return c.front(); } + void push(const value_type& x); + void pop(); + }; + // no equality is provided + } ++ +
to:
+ +namespace std { + template <class T, class Container = vector<T>, + class Compare = less<typename Container::value_type> > + class priority_queue { + public: + typedef typename Container::value_type value_type; + typedef typename Container::reference reference; + typedef typename Container::const_reference const_reference; + typedef typename Container::size_type size_type; + typedef Container container_type; + protected: + Container c; + Compare comp; + + public: + explicit priority_queue(const Compare& x = Compare(), + const Container& = Container()); + template <class InputIterator> + priority_queue(InputIterator first, InputIterator last, + const Compare& x = Compare(), + const Container& = Container()); + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + const_reference top() const { return c.front(); } + void push(const value_type& x); + void pop(); + }; + // no equality is provided + } ++ +
And change 23.2.3.3/1 from:
+ +namespace std { + template <class T, class Container = deque<T> > + class stack { + public: + typedef typename Container::value_type value_type; + typedef typename Container::size_type size_type; + typedef Container container_type; + protected: + Container c; + + public: + explicit stack(const Container& = Container()); + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + value_type& top() { return c.back(); } + const value_type& top() const { return c.back(); } + void push(const value_type& x) { c.push_back(x); } + void pop() { c.pop_back(); } + }; + + template <class T, class Container> + bool operator==(const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator< (const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator!=(const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator> (const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator>=(const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator<=(const stack<T, Container>& x, + const stack<T, Container>& y); + } ++ +
to:
+ +namespace std { + template <class T, class Container = deque<T> > + class stack { + public: + typedef typename Container::value_type value_type; + typedef typename Container::reference reference; + typedef typename Container::const_reference const_reference; + typedef typename Container::size_type size_type; + typedef Container container_type; + protected: + Container c; + + public: + explicit stack(const Container& = Container()); + + bool empty() const { return c.empty(); } + size_type size() const { return c.size(); } + reference top() { return c.back(); } + const_reference top() const { return c.back(); } + void push(const value_type& x) { c.push_back(x); } + void pop() { c.pop_back(); } + }; + + template <class T, class Container> + bool operator==(const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator< (const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator!=(const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator> (const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator>=(const stack<T, Container>& x, + const stack<T, Container>& y); + template <class T, class Container> + bool operator<=(const stack<T, Container>& x, + const stack<T, Container>& y); + } ++ +
[Copenhagen: This change was discussed before the IS was released +and it was deliberately not adopted. Nevertheless, the LWG believes +(straw poll: 10-2) that it is a genuine defect.]
+ + + + + + +Section: 27 [input.output] Status: WP + Submitter: Martin Sebor Date: 2001-03-15
+View all other issues in [input.output].
+View all issues with WP status.
+Discussion:
++Table 82 in section 27 mentions the header <cstdlib> for String +streams (27.7 [string.streams]) and the headers <cstdio> and +<cwchar> for File streams (27.8 [file.streams]). It's not clear +why these headers are mentioned in this context since they do not +define any of the library entities described by the +subclauses. According to 17.4.1.1 [contents], only such headers +are to be listed in the summary. +
+ + +Proposed resolution:
+Remove <cstdlib> and <cwchar> from +Table 82.
+ +[Copenhagen: changed the proposed resolution slightly. The +original proposed resolution also said to remove <cstdio> from +Table 82. However, <cstdio> is mentioned several times within +section 27.8 [file.streams], including 27.8.2 [c.files].]
+ + + + + + +Section: 17.4.1.2 [headers], 19.3 [errno] Status: WP + Submitter: Steve Clamage Date: 2001-03-21
+View all other issues in [headers].
+View all issues with WP status.
+Discussion:
++ Exactly how should errno be declared in a conforming C++ header? +
+ ++ The C standard says in 7.1.4 that it is unspecified whether errno is a + macro or an identifier with external linkage. In some implementations + it can be either, depending on compile-time options. (E.g., on + Solaris in multi-threading mode, errno is a macro that expands to a + function call, but is an extern int otherwise. "Unspecified" allows + such variability.) +
+ +The C++ standard:
+I find no other references to errno.
+ +We should either explicitly say that errno must be a macro, even + though it need not be a macro in C, or else explicitly leave it + unspecified. We also need to say something about namespace std. + A user who includes <cerrno> needs to know whether to write + errno, or ::errno, or std::errno, or + else <cerrno> is useless.
+ +Two acceptable fixes:
+errno must be a macro. This is trivially satisfied by adding
+ #define errno (::std::errno)
+ to the headers if errno is not already a macro. You then always
+ write errno without any scope qualification, and it always expands
+ to a correct reference. Since it is always a macro, you know to
+ avoid using errno as a local identifer.
errno is in the global namespace. This fix is inferior, because + ::errno is not guaranteed to be well-formed.
[ + This issue was first raised in 1999, but it slipped through + the cracks. + ]
+ + + +Proposed resolution:
+Change the Note in section 17.4.1.2p5 from
+ ++ ++ Note: the names defined as macros in C include the following: + assert, errno, offsetof, setjmp, va_arg, va_end, and va_start. +
to
+ ++ ++ Note: the names defined as macros in C include the following: + assert, offsetof, setjmp, va_arg, va_end, and va_start. +
In section 19.3, change paragraph 2 from
+ ++ ++ The contents are the same as the Standard C library header + <errno.h>. +
to
+ ++ + ++ The contents are the same as the Standard C library header + <errno.h>, except that errno shall be defined as a macro. +
Rationale:
+C++ must not leave it up to the implementation to decide whether or +not a name is a macro; it must explicitly specify exactly which names +are required to be macros. The only one that really works is for it +to be a macro.
+ +[Curaçao: additional rationale added.]
+ + + + + + + +Section: 27.6.2.1 [ostream] Status: WP + Submitter: Andy Sawyer Date: 2001-03-21
+View all other issues in [ostream].
+View all issues with WP status.
+Discussion:
+ +In 27.6.2.1 [ostream], the synopsis of class basic_ostream says:
+ +// partial specializationss + template<class traits> + basic_ostream<char,traits>& operator<<( basic_ostream<char,traits>&, + const char * ); ++ +
Problems:
+Proposed resolution:
+In the synopsis in 27.6.2.1 [ostream], remove the +// partial specializationss comment. Also remove the same +comment (correctly spelled, but still incorrect) from the synopsis in +27.6.2.6.4 [ostream.inserters.character]. +
+ +[ +Pre-Redmond: added 27.6.2.6.4 [ostream.inserters.character] because of Martin's +comment in c++std-lib-8939. +]
+ + + + + + + +Section: 20 [utilities] Status: WP + Submitter: Martin Sebor Date: 2001-03-29
+View all issues with WP status.
+Discussion:
+Table 27 in section 20 lists the header <memory> (only) for +Memory (lib.memory) but neglects to mention the headers +<cstdlib> and <cstring> that are discussed in 20.5.5 [meta.rel].
+ + +Proposed resolution:
+Add <cstdlib> and <cstring> to Table 27, in the same row +as <memory>.
+ + + + + +Section: 23.2.4.4 [list.ops] Status: WP + Submitter: Andy Sawyer Date: 2001-05-01
+View all other issues in [list.ops].
+View all issues with WP status.
+Discussion:
++23.2.4.4 [list.ops], Para 21 describes the complexity of +list::unique as: "If the range (last - first) is not empty, exactly +(last - first) -1 applications of the corresponding predicate, +otherwise no applications of the predicate)". +
+ ++"(last - first)" is not a range. +
+ + +Proposed resolution:
++Change the "range" from (last - first) to [first, last). +
+ + + + +Section: 23.1.4 [associative.reqmts] Status: WP + Submitter: Martin Sebor Date: 2001-05-04
+View all other issues in [associative.reqmts].
+View all issues with WP status.
+Discussion:
+Table 69 says this about a_uniq.insert(t):
+ ++ ++inserts t if and only if there is no element in the container with key +equivalent to the key of t. The bool component of the returned pair +indicates whether the insertion takes place and the iterator component of the +pair points to the element with key equivalent to the key of t. +
The description should be more specific about exactly how the bool component +indicates whether the insertion takes place.
+ + +Proposed resolution:
+Change the text in question to
+ ++ + + + + ++...The bool component of the returned pair is true if and only if the insertion +takes place... +
Section: 22 [localization] Status: WP + Submitter: Martin Sebor Date: 2001-05-04
+View all other issues in [localization].
+View all issues with WP status.
+Discussion:
++The localization section of the standard refers to specializations of +the facet templates as instantiations even though the required facets +are typically specialized rather than explicitly (or implicitly) +instantiated. In the case of ctype<char> and +ctype_byname<char> (and the wchar_t versions), these facets are +actually required to be specialized. The terminology should be +corrected to make it clear that the standard doesn't mandate explicit +instantiation (the term specialization encompasses both explicit +instantiations and specializations). +
+ + +Proposed resolution:
++In the following paragraphs, replace all occurrences of the word +instantiation or instantiations with specialization or specializations, +respectively: +
+ ++ ++22.1.1.1.1, p4, Table 52, 22.2.1.1, p2, 22.2.1.5, p3, 22.2.1.5.1, p5, +22.2.1.5.2, p10, 22.2.2, p2, 22.2.3.1, p1, 22.2.3.1.2, p1, p2 and p3, +22.2.4.1, p1, 22.2.4.1.2, p1, 22,2,5, p1, 22,2,6, p2, 22.2.6.3.2, p7, and +Footnote 242. +
And change the text in 22.1.1.1.1, p4 from
+ ++ ++ An implementation is required to provide those instantiations + for facet templates identified as members of a category, and + for those shown in Table 52: +
to
+ ++ ++ An implementation is required to provide those specializations... +
[Nathan will review these changes, and will look for places where +explicit specialization is necessary.]
+ + + + +Rationale:
+This is a simple matter of outdated language. The language to +describe templates was clarified during the standardization process, +but the wording in clause 22 was never updated to reflect that +change.
+ + + + + + + +Section: 22.2.3.2 [locale.numpunct.byname] Status: WP + Submitter: Martin Sebor Date: 2001-05-12
+View all issues with WP status.
+Discussion:
+The definition of the numpunct_byname template contains the following +comment:
+ +namespace std { + template <class charT> + class numpunct_byname : public numpunct<charT> { + // this class is specialized for char and wchar_t. + ... ++ +
There is no documentation of the specializations and it seems +conceivable that an implementation will not explicitly specialize the +template at all, but simply provide the primary template.
+ + +Proposed resolution:
+Remove the comment from the text in 22.2.3.2 and from the proposed +resolution of library issue 228.
+ + + + +Section: 18.5.1.1 [new.delete.single], 18.5.1.2 [new.delete.array] Status: WP + Submitter: Beman Dawes Date: 2001-05-15
+View all other issues in [new.delete.single].
+View all issues with WP status.
+Discussion:
+The standard specifies 17.3.1.3 [structure.specifications] that "Required +behavior" elements describe "the semantics of a function definition +provided by either the implementation or a C++ program."
+ +The standard specifies 17.3.1.3 [structure.specifications] that "Requires" +elements describe "the preconditions for calling the function."
+ +In the sections noted below, the current wording specifies +"Required Behavior" for what are actually preconditions, and thus +should be specified as "Requires".
+ + + +Proposed resolution:
+ +In 18.5.1.1 [new.delete.single] Para 12 Change:
+++Required behavior: accept a value of ptr that is null or that was + returned by an earlier call ...
+
to:
+++ +Requires: the value of ptr is null or the value returned by an + earlier call ...
+
In 18.5.1.2 [new.delete.array] Para 11 Change:
+++Required behavior: accept a value of ptr that is null or that was + returned by an earlier call ...
+
to:
+++ + + + + +Requires: the value of ptr is null or the value returned by an + earlier call ...
+
Section: 23.2.4.1 [list.cons] Status: WP + Submitter: Howard Hinnant Date: 2001-05-17
+View all other issues in [list.cons].
+View all issues with WP status.
+Discussion:
++Section 23.2.4.1 [list.cons], paragraphs 6-8 specify that list assign (both forms) have +the "effects" of a call to erase followed by a call to insert. +
+ ++I would like to document that implementers have the freedom to implement +assign by other methods, as long as the end result is the same and the +exception guarantee is as good or better than the basic guarantee. +
+ ++The motivation for this is to use T's assignment operator to recycle +existing nodes in the list instead of erasing them and reallocating +them with new values. It is also worth noting that, with careful +coding, most common cases of assign (everything but assignment with +true input iterators) can elevate the exception safety to strong if +T's assignment has a nothrow guarantee (with no extra memory cost). +Metrowerks does this. However I do not propose that this subtlety be +standardized. It is a QoI issue.
+ +Existing practise: +Metrowerks and SGI recycle nodes, Dinkumware and Rogue Wave don't. +
+ + +Proposed resolution:
+Change 23.2.4.1 [list.cons]/7 from:
+ +++ +Effects:
+ +erase(begin(), end()); + insert(begin(), first, last); ++
to:
+ +++ +Effects: Replaces the contents of the list with the range [first, last).
+
In 23.1.3 [sequence.reqmts], in Table 67 (sequence requirements), +add two new rows:
+a.assign(i,j) void pre: i,j are not iterators into a. + Replaces elements in a with a copy + of [i, j). + + a.assign(n,t) void pre: t is not a reference into a. + Replaces elements in a with n copies + of t. ++ +
Change 23.2.4.1 [list.cons]/8 from:
+ +++Effects:
+erase(begin(), end()); + insert(begin(), n, t); ++
to:
+ +++ +Effects: Replaces the contents of the list with n copies of t.
+
[Redmond: Proposed resolution was changed slightly. Previous +version made explicit statement about exception safety, which wasn't +consistent with the way exception safety is expressed elsewhere. +Also, the change in the sequence requirements is new. Without that +change, the proposed resolution would have required that assignment of +a subrange would have to work. That too would have been +overspecification; it would effectively mandate that assignment use a +temporary. Howard provided wording. +]
+ + +[Curaçao: Made editorial improvement in wording; changed +"Replaces elements in a with copies of elements in [i, j)." +with "Replaces the elements of a with a copy of [i, j)." +Changes not deemed serious enough to requre rereview.]
+ + + + + + + +Section: 22.2.2.1.2 [facet.num.get.virtuals] Status: WP + Submitter: Kevin Djang Date: 2001-05-17
+View other active issues in [facet.num.get.virtuals].
+View all other issues in [facet.num.get.virtuals].
+View all issues with WP status.
+Discussion:
++Section 22.2.2.1.2 at p7 states that "A length specifier is added to +the conversion function, if needed, as indicated in Table 56." +However, Table 56 uses the term "length modifier", not "length +specifier". +
+ + +Proposed resolution:
++In 22.2.2.1.2 at p7, change the text "A length specifier is added ..." +to be "A length modifier is added ..." +
+ + +Rationale:
+C uses the term "length modifier". We should be consistent.
+ + + + + + +Section: 23.1 [container.requirements] Status: WP + Submitter: Matt Austern Date: 2001-05-17
+View other active issues in [container.requirements].
+View all other issues in [container.requirements].
+View all issues with WP status.
+Discussion:
++It's widely assumed that, if X is a container, +iterator_traits<X::iterator>::value_type and +iterator_traits<X::const_iterator>::value_type should both be +X::value_type. However, this is nowhere stated. The language in +Table 65 is not precise about the iterators' value types (it predates +iterator_traits), and could even be interpreted as saying that +iterator_traits<X::const_iterator>::value_type should be "const +X::value_type". +
+ +Related issue: 279.
+ + +Proposed resolution:
+In Table 65 ("Container Requirements"), change the return type for +X::iterator to "iterator type whose value type is T". Change the +return type for X::const_iterator to "constant iterator type whose +value type is T".
+ + +Rationale:
++This belongs as a container requirement, rather than an iterator +requirement, because the whole notion of iterator/const_iterator +pairs is specific to containers' iterator. +
++It is existing practice that (for example) +iterator_traits<list<int>::const_iterator>::value_type +is "int", rather than "const int". This is consistent with +the way that const pointers are handled: the standard already +requires that iterator_traits<const int*>::value_type is int. +
+ + + + + +Section: 24.1.2 [output.iterators] Status: WP + Submitter: Dave Abrahams Date: 2001-06-07
+View all other issues in [output.iterators].
+View all issues with WP status.
+Discussion:
+ +Table 73 suggests that output iterators have value types. It +requires the expression "*a = t". Additionally, although Table 73 +never lists "a = t" or "X(a) = t" in the "expressions" column, it +contains a note saying that "a = t" and "X(a) = t" have equivalent +(but nowhere specified!) semantics.
+ +According to 24.1/9, t is supposed to be "a value of value type +T":
+ ++ ++ In the following sections, a and b denote values of X, n denotes a + value of the difference type Distance, u, tmp, and m denote + identifiers, r denotes a value of X&, t denotes a value of + value type T. +
Two other parts of the standard that are relevant to whether +output iterators have value types:
+ +The first of these passages suggests that "*i" is supposed to +return a useful value, which contradicts the note in 24.1.2/2 saying +that the only valid use of "*i" for output iterators is in an +expression of the form "*i = t". The second of these passages appears +to contradict Table 73, because it suggests that "*i"'s return value +should be void. The second passage is also broken in the case of a an +iterator type, like non-const pointers, that satisfies both the output +iterator requirements and the forward iterator requirements.
+ +What should the standard say about *i's return value when +i is an output iterator, and what should it say about that t is in the +expression "*i = t"? Finally, should the standard say anything about +output iterators' pointer and reference types?
+ + + +Proposed resolution:
+24.1 p1, change
+ +++ +All iterators i support the expression *i, resulting +in a value of some class, enumeration, or built-in type T, +called the value type of the iterator.
+
to
+ +++ +All input iterators i support the expression *i, +resulting in a value of some class, enumeration, or built-in type +T, called the value type of the iterator. All output +iterators support the expression *i = o where o is a +value of some type that is in the set of types that are writable to +the particular iterator type of i. +
+
24.1 p9, add
+ +++ +o denotes a value of some type that is writable to the +output iterator. +
+
Table 73, change
+ +++ +*a = t ++
to
+ +++ +*r = o ++
and change
+ +++ +*r++ = t ++
to
+ +++ +*r++ = o ++
[post-Redmond: Jeremy provided wording]
+ + + + +Rationale:
+The LWG considered two options: change all of the language that +seems to imply that output iterators have value types, thus making it +clear that output iterators have no value types, or else define value +types for output iterator consistently. The LWG chose the former +option, because it seems clear that output iterators were never +intended to have value types. This was a deliberate design decision, +and any language suggesting otherwise is simply a mistake.
+ +A future revision of the standard may wish to revisit this design +decision.
+ + + + + +Section: 22.2.6.3.2 [locale.moneypunct.virtuals] Status: WP + Submitter: Martin Sebor Date: 2001-07-02
+View all other issues in [locale.moneypunct.virtuals].
+View all issues with WP status.
+Discussion:
+The Returns clause in 22.2.6.3.2, p3 says about +moneypunct<charT>::do_grouping() +
+ ++ ++ Returns: A pattern defined identically as the result of + numpunct<charT>::do_grouping().241) +
Footnote 241 then reads
+ ++ ++ This is most commonly the value "\003" (not "3"). +
+The returns clause seems to imply that the two member functions must +return an identical value which in reality may or may not be true, +since the facets are usually implemented in terms of struct std::lconv +and return the value of the grouping and mon_grouping, respectively. +The footnote also implies that the member function of the moneypunct +facet (rather than the overridden virtual functions in moneypunct_byname) +most commonly return "\003", which contradicts the C standard which +specifies the value of "" for the (most common) C locale. +
+ + + +Proposed resolution:
+Replace the text in Returns clause in 22.2.6.3.2, p3 with the following:
+ ++ ++ Returns: A pattern defined identically as, but not necessarily + equal to, the result of numpunct<charT>::do_grouping().241) +
and replace the text in Footnote 241 with the following:
+ ++ + ++ To specify grouping by 3s the value is "\003", not "3". +
Rationale:
++The fundamental problem is that the description of the locale facet +virtuals serves two purposes: describing the behavior of the base +class, and describing the meaning of and constraints on the behavior +in arbitrary derived classes. The new wording makes that separation a +little bit clearer. The footnote (which is nonnormative) is not +supposed to say what the grouping is in the "C" locale or in any other +locale. It is just a reminder that the values are interpreted as small +integers, not ASCII characters. +
+ + + + +Section: 22.1.1.1.1 [locale.category] Status: WP + Submitter: Tiki Wan Date: 2001-07-06
+View all other issues in [locale.category].
+View all issues with WP status.
+Duplicate of: 447
+Discussion:
+The wchar_t versions of time_get and +time_get_byname are listed incorrectly in table 52, +required instantiations. In both cases the second template +parameter is given as OutputIterator. It should instead be +InputIterator, since these are input facets.
+ + +Proposed resolution:
++In table 52, required instantiations, in +22.1.1.1.1 [locale.category], change
+time_get<wchar_t, OutputIterator> + time_get_byname<wchar_t, OutputIterator> ++
to
+time_get<wchar_t, InputIterator> + time_get_byname<wchar_t, InputIterator> ++ +
[Redmond: Very minor change in proposed resolution. Original had +a typo, wchart instead of wchar_t.]
+ + + + + + +Section: 22.2.6.2.2 [locale.money.put.virtuals] Status: WP + Submitter: Martin Sebor Date: 2001-07-07
+View all issues with WP status.
+Discussion:
+The sprintf format string , "%.01f" (that's the digit one), in the +description of the do_put() member functions of the money_put facet in +22.2.6.2.2, p1 is incorrect. First, the f format specifier is wrong +for values of type long double, and second, the precision of 01 +doesn't seem to make sense. What was most likely intended was +"%.0Lf"., that is a precision of zero followed by the L length +modifier.
+ + +Proposed resolution:
+Change the format string to "%.0Lf".
+ + +Rationale:
Fixes an obvious typo
+ + + + +Section: 23.2.6.2 [vector.capacity], 23.2.6.4 [vector.modifiers] Status: WP + Submitter: Anthony Williams Date: 2001-07-13
+View all other issues in [vector.capacity].
+View all issues with WP status.
+Discussion:
++There is an apparent contradiction about which circumstances can cause +a reallocation of a vector in Section 23.2.6.2 [vector.capacity] and +section 23.2.6.4 [vector.modifiers]. +
+ +23.2.6.2 [vector.capacity],p5 says:
++ ++Notes: Reallocation invalidates all the references, pointers, and iterators +referring to the elements in the sequence. It is guaranteed that no +reallocation takes place during insertions that happen after a call to +reserve() until the time when an insertion would make the size of the vector +greater than the size specified in the most recent call to reserve(). +
Which implies if I do
+ +std::vector<int> vec; + vec.reserve(23); + vec.reserve(0); + vec.insert(vec.end(),1); ++ +
then the implementation may reallocate the vector for the insert, +as the size specified in the previous call to reserve was zero.
+ +However, the previous paragraphs (23.2.6.2 [vector.capacity], p1-2) state:
+++ ++(capacity) Returns: The total number of elements the vector +can hold without requiring reallocation +
++...After reserve(), capacity() is greater or equal to the +argument of reserve if reallocation happens; and equal to the previous value +of capacity() otherwise... +
+
+This implies that vec.capacity() is still 23, and so the insert() +should not require a reallocation, as vec.size() is 0. This is backed +up by 23.2.6.4 [vector.modifiers], p1: +
++ ++(insert) Notes: Causes reallocation if the new size is greater than the old +capacity. +
+Though this doesn't rule out reallocation if the new size is less +than the old capacity, I think the intent is clear. +
+ + + +Proposed resolution:
+Change the wording of 23.2.6.2 [vector.capacity] paragraph 5 to:
+ ++ ++Notes: Reallocation invalidates all the references, pointers, and +iterators referring to the elements in the sequence. It is guaranteed +that no reallocation takes place during insertions that happen after a +call to reserve() until the time when an insertion would make the size +of the vector greater than the value of capacity(). +
[Redmond: original proposed resolution was modified slightly. In +the original, the guarantee was that there would be no reallocation +until the size would be greater than the value of capacity() after the +most recent call to reserve(). The LWG did not believe that the +"after the most recent call to reserve()" added any useful +information.]
+ + + + +Rationale:
+There was general agreement that, when reserve() is called twice in +succession and the argument to the second invocation is smaller than +the argument to the first, the intent was for the second invocation to +have no effect. Wording implying that such cases have an effect on +reallocation guarantees was inadvertant.
+ + + + + +Section: 27.4.2.1.1 [ios::failure] Status: WP + Submitter: PremAnand M. Rao Date: 2001-08-23
+View all other issues in [ios::failure].
+View all issues with WP status.
+Discussion:
++With the change in 17.4.4.9 [res.on.exception.handling] to state + "An implementation may strengthen the exception-specification for a + non-virtual function by removing listed exceptions." +(issue 119) +and the following declaration of ~failure() in ios_base::failure +
+namespace std { + class ios_base::failure : public exception { + public: + ... + virtual ~failure(); + ... + }; + } ++
the class failure cannot be implemented since in 18.6.1 [type.info] the destructor of class exception has an empty +exception specification:
+namespace std { + class exception { + public: + ... + virtual ~exception() throw(); + ... + }; + } ++ + +
Proposed resolution:
+Remove the declaration of ~failure().
+ + +Rationale:
+The proposed resolution is consistent with the way that destructors +of other classes derived from exception are handled.
+ + + + + + + +Section: 27.6.2.8 [ostream.manip] Status: WP + Submitter: PremAnand M. Rao Date: 2001-08-27
+View all issues with WP status.
+Discussion:
+A footnote in 27.6.2.8 [ostream.manip] states:
++ ++ [Footnote: The effect of executing cout << endl is to insert a + newline character in the output sequence controlled by cout, then + synchronize it with any external file with which it might be + associated. --- end foonote] +
+Does the term "file" here refer to the external device? +This leads to some implementation ambiguity on systems with fully +buffered files where a newline does not cause a flush to the device. +
+ ++Choosing to sync with the device leads to significant performance +penalties for each call to endl, while not sync-ing leads to +errors under special circumstances. +
+ ++I could not find any other statement that explicitly defined +the behavior one way or the other. +
+ + +Proposed resolution:
+Remove footnote 300 from section 27.6.2.8 [ostream.manip].
+ + +Rationale:
+We already have normative text saying what endl does: it +inserts a newline character and calls flush. This footnote +is at best redundant, at worst (as this issue says) misleading, +because it appears to make promises about what flush +does.
+ + + + + + + +Section: 23.3.1.2 [map.access] Status: WP + Submitter: Andrea Griffini Date: 2001-09-02
+View all other issues in [map.access].
+View all issues with WP status.
+Discussion:
++The current standard describes map::operator[] using a +code example. That code example is however quite +inefficient because it requires several useless copies +of both the passed key_type value and of default +constructed mapped_type instances. +My opinion is that was not meant by the comitee to +require all those temporary copies. +
+ +Currently map::operator[] behaviour is specified as:
+Returns: + (*((insert(make_pair(x, T()))).first)).second. ++ +
+This specification however uses make_pair that is a +template function of which parameters in this case +will be deduced being of type const key_type& and +const T&. This will create a pair<key_type,T> that +isn't the correct type expected by map::insert so +another copy will be required using the template +conversion constructor available in pair to build +the required pair<const key_type,T> instance. +
+ +If we consider calling of key_type copy constructor +and mapped_type default constructor and copy +constructor as observable behaviour (as I think we +should) then the standard is in this place requiring +two copies of a key_type element plus a default +construction and two copy construction of a mapped_type +(supposing the addressed element is already present +in the map; otherwise at least another copy +construction for each type). +
+ +A simple (half) solution would be replacing the description with:
+Returns: + (*((insert(value_type(x, T()))).first)).second. ++ +
This will remove the wrong typed pair construction that +requires one extra copy of both key and value.
+ +However still the using of map::insert requires temporary +objects while the operation, from a logical point of view, +doesn't require any.
+ +I think that a better solution would be leaving free an +implementer to use a different approach than map::insert +that, because of its interface, forces default constructed +temporaries and copies in this case. +The best solution in my opinion would be just requiring +map::operator[] to return a reference to the mapped_type +part of the contained element creating a default element +with the specified key if no such an element is already +present in the container. Also a logarithmic complexity +requirement should be specified for the operation. +
+ ++This would allow library implementers to write alternative +implementations not using map::insert and reaching optimal +performance in both cases of the addressed element being +present or absent from the map (no temporaries at all and +just the creation of a new pair inside the container if +the element isn't present). +Some implementer has already taken this option but I think +that the current wording of the standard rules that as +non-conforming. +
+ + + +Proposed resolution:
+ ++Replace 23.3.1.2 [map.access] paragraph 1 with +
+++ ++-1- Effects: If there is no key equivalent to x in the map, inserts +value_type(x, T()) into the map. +
++-2- Returns: A reference to the mapped_type corresponding to x in *this. +
++-3- Complexity: logarithmic. +
+
[This is the second option mentioned above. Howard provided +wording. We may also wish to have a blanket statement somewhere in +clause 17 saying that we do not intend the semantics of sample code +fragments to be interpreted as specifing exactly how many copies are +made. See issue 98 for a similar problem.]
+ + + + +Rationale:
++This is the second solution described above; as noted, it is +consistent with existing practice. +
+ +Note that we now need to specify the complexity explicitly, because +we are no longer defining operator[] in terms of +insert.
+ + + + + +Section: 21.1.1 [char.traits.require] Status: WP + Submitter: Andy Sawyer Date: 2001-09-06
+View all issues with WP status.
+Discussion:
++Table 37, in 21.1.1 [char.traits.require], descibes char_traits::assign +as: +
+X::assign(c,d) assigns c = d. ++ +
And para 1 says:
+ ++ ++ [...] c and d denote values of type CharT [...] +
+Naturally, if c and d are values, then the assignment is +(effectively) meaningless. It's clearly intended that (in the case of +assign, at least), 'c' is intended to be a reference type. +
+ +I did a quick survey of the four implementations I happened to have +lying around, and sure enough they all have signatures:
+assign( charT&, const charT& ); ++ +
(or the equivalent). It's also described this way in Nico's book. +(Not to mention the synopses of char_traits<char> in 21.1.3.1 +and char_traits<wchar_t> in 21.1.3.2...) +
+ + +Proposed resolution:
+Add the following to 21.1.1 para 1:
++ ++ r denotes an lvalue of CharT +
and change the description of assign in the table to:
+X::assign(r,d) assigns r = d ++ + + + + +
Section: 17 [library] Status: WP + Submitter: Detlef Vollmann Date: 2001-09-05
+View all other issues in [library].
+View all issues with WP status.
+Discussion:
+From c++std-edit-873:
+ +17.4.1.2 [headers], Table 11. In this table, the header +<strstream> is missing.
+ +This shows a general problem: The whole clause 17 refers quite +often to clauses 18 through 27, but D.7 is also a part of the standard +library (though a deprecated one).
+ + + +Proposed resolution:
+ +To 17.4.1.2 [headers] Table 11, C++ Library Headers, add +"<strstream>".
+ +In the following places, change "clauses 17 through 27" to "clauses +17 through 27 and Annex D":
+ +Section: 25.2.5 [alg.replace] Status: WP + Submitter: Detlef Vollmann Date: 2001-09-07
+View all other issues in [alg.replace].
+View all issues with WP status.
+Discussion:
+From c++std-edit-876:
+ ++In section 25.2.5 [alg.replace] before p4: The name of the first +parameter of template replace_copy_if should be "InputIterator" +instead of "Iterator". According to 17.3.2.1 [type.descriptions] p1 the +parameter name conveys real normative meaning. +
+ + +Proposed resolution:
+Change Iterator to InputIterator.
+ + + + + +Section: 22.2 [locale.categories] Status: WP + Submitter: Martin Sebor Date: 2001-09-17
+View other active issues in [locale.categories].
+View all other issues in [locale.categories].
+View all issues with WP status.
+Discussion:
++From Stage 2 processing in 22.2.2.1.2 [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 [locale.numpunct], p2, which gives the +format for integer and floating point values, says that whitespace is +optional between a plusminus and a sign. +
+ ++The text needs to be clarified to either consistently allow or +disallow whitespace between a plusminus and a sign. It might be +worthwhile to consider the fact that the C library stdio facility does +not permit whitespace embedded in numbers and neither does the C or +C++ core language (the syntax of integer-literals is given in 2.13.1 +[lex.icon], that of floating-point-literals in 2.13.3 [lex.fcon] of the +C++ standard). +
+ + +Proposed resolution:
+Change the first part of 22.2.3.1 [locale.numpunct] paragraph 2 from:
++++The syntax for number formats is as follows, where digit +represents the radix set specified by the fmtflags argument +value, whitespace is as determined by the facet +ctype<charT> (22.2.1.1), and thousands-sep and +decimal-point are the results of corresponding +numpunct<charT> members. Integer values have the +format: +
+integer ::= [sign] units + sign ::= plusminus [whitespace] + plusminus ::= '+' | '-' + units ::= digits [thousands-sep units] + digits ::= digit [digits] ++
to:
+++ + ++The syntax for number formats is as follows, where digit +represents the radix set specified by the fmtflags argument +value, and thousands-sep and decimal-point are the +results of corresponding numpunct<charT> members. +Integer values have the format: +
+integer ::= [sign] units + sign ::= plusminus + plusminus ::= '+' | '-' + units ::= digits [thousands-sep units] + digits ::= digit [digits] ++
Rationale:
+It's not clear whether the format described in 22.2.3.1 [locale.numpunct] paragraph 2 has any normative weight: nothing in the +standard says how, or whether, it's used. However, there's no reason +for it to differ gratuitously from the very specific description of +numeric processing in 22.2.2.1.2 [facet.num.get.virtuals]. The proposed +resolution removes all mention of "whitespace" from that format.
+ + + + + +Section: 22.2.1 [category.ctype], 17.3.2.1.2 [bitmask.types] Status: WP + Submitter: Martin Sebor Date: 2001-09-17
+View all other issues in [category.ctype].
+View all issues with WP status.
+Discussion:
+The ctype_category::mask type is declared to be an enum in 22.2.1 +[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 +[bitmask.types], p1. However, the said definition only applies to +clause 27, making the reference in 22.2.1 somewhat dubious. +
+ + +Proposed resolution:
+Clarify 17.3.2.1.2, p1 by changing the current text from
+++ Several types defined in clause 27 are bitmask types. Each bitmask type + can be implemented as an enumerated type that overloads certain operators, + as an integer type, or as a bitset (23.3.5 [template.bitset]). +
to read
++ ++ Several types defined in clauses lib.language.support through + lib.input.output and Annex D are bitmask types. Each bitmask type can + be implemented as an enumerated type that overloads certain operators, + as an integer type, or as a bitset (lib.template.bitset). +
+Additionally, change the definition in 22.2.1 to adopt the same +convention as in clause 27 by replacing the existing text with the +following (note, in particluar, the cross-reference to 17.3.2.1.2 in +22.2.1, p1): +
+ +++ +22.2.1 The ctype category [lib.category.ctype]
+namespace std { + class ctype_base { + public: + typedef T mask; + + // numeric values are for exposition only. + static const mask space = 1 << 0; + static const mask print = 1 << 1; + static const mask cntrl = 1 << 2; + static const mask upper = 1 << 3; + static const mask lower = 1 << 4; + static const mask alpha = 1 << 5; + static const mask digit = 1 << 6; + static const mask punct = 1 << 7; + static const mask xdigit = 1 << 8; + static const mask alnum = alpha | digit; + static const mask graph = alnum | punct; + }; +} ++ +The type mask is a bitmask type (17.3.2.1.2 [bitmask.types]).
+
[Curaçao: The LWG notes that T above should be bold-italics to be +consistent with the rest of the standard.]
+ + + + + + + + + +Section: 22.1.1.1.1 [locale.category] Status: WP + Submitter: Martin Sebor Date: 2001-09-18
+View all other issues in [locale.category].
+View all issues with WP status.
+Discussion:
++It's unclear whether 22.1.1.1.1, p3 says that +has_facet<Facet>(loc) returns true for any Facet +from Table 51 or whether it includes Table 52 as well: +
+ ++ ++For any locale loc either constructed, or returned by +locale::classic(), and any facet Facet that is a member of a +standard category, has_facet<Facet>(loc) is true. Each +locale member function which takes a locale::category +argument operates on the corresponding set of facets. +
+It seems that it comes down to which facets are considered to be members of a +standard category. Intuitively, I would classify all the facets in Table 52 as +members of their respective standard categories, but there are an unbounded set +of them... +
+ ++The paragraph implies that, for instance, has_facet<num_put<C, +OutputIterator> >(loc) must always return true. I don't think that's +possible. If it were, then use_facet<num_put<C, OutputIterator> +>(loc) would have to return a reference to a distinct object for each +valid specialization of num_put<C, OutputIteratory>, which is +clearly impossible. +
+ ++On the other hand, if none of the facets in Table 52 is a member of a standard +category then none of the locale member functions that operate on entire +categories of facets will work properly. +
+ ++It seems that what p3 should mention that it's required (permitted?) +to hold only for specializations of Facet from Table 52 on +C from the set { char, wchar_t }, and +InputIterator and OutputIterator from the set of +{ +{i,o}streambuf_iterator<{char,wchar_t}> +}. +
+ + +Proposed resolution:
+In 22.1.1.1.1 [locale.category], paragraph 3, change +"that is a member of a standard category" to "shown in Table 51".
+ + +Rationale:
+The facets in Table 52 are an unbounded set. Locales should not be +required to contain an infinite number of facets.
+ +It's not necessary to talk about which values of InputIterator and +OutputIterator must be supported. Table 51 already contains a +complete list of the ones we need.
+ + + + + + +Section: 23.2.6.2 [vector.capacity] Status: WP + Submitter: Anthony Williams Date: 2001-09-27
+View all other issues in [vector.capacity].
+View all issues with WP status.
+Discussion:
+It is a common idiom to reduce the capacity of a vector by swapping it with +an empty one:
+std::vector<SomeType> vec; + // fill vec with data + std::vector<SomeType>().swap(vec); + // vec is now empty, with minimal capacity ++ +
However, the wording of 23.2.6.2 [vector.capacity]paragraph 5 prevents +the capacity of a vector being reduced, following a call to +reserve(). This invalidates the idiom, as swap() is thus prevented +from reducing the capacity. The proposed wording for issue 329 does not affect this. Consequently, the example above +requires the temporary to be expanded to cater for the contents of +vec, and the contents be copied across. This is a linear-time +operation.
+ +However, the container requirements state that swap must have constant +complexity (23.1 [container.requirements] note to table 65).
+ +This is an important issue, as reallocation affects the validity of +references and iterators.
+ +If the wording of 23.2.4.2p5 is taken to be the desired intent, then +references and iterators remain valid after a call to swap, if they refer to +an element before the new end() of the vector into which they originally +pointed, in which case they refer to the element at the same index position. +Iterators and references that referred to an element whose index position +was beyond the new end of the vector are invalidated.
+ +If the note to table 65 is taken as the desired intent, then there are two +possibilities with regard to iterators and references:
+ +Proposed resolution:
+Add a new paragraph after 23.2.6.2 [vector.capacity] paragraph 5:
+++ +void swap(vector<T,Allocator>& x); ++Effects: Exchanges the contents and capacity() of *this +with that of x.
+Complexity: Constant time.
+
[This solves the problem reported for this issue. We may also +have a problem with a circular definition of swap() for other +containers.]
+ + + + +Rationale:
++swap should be constant time. The clear intent is that it should just +do pointer twiddling, and that it should exchange all properties of +the two vectors, including their reallocation guarantees. +
+ + + + + +Section: 21.5 [c.strings] Status: WP + Submitter: Clark Nelson Date: 2001-10-19
+View all other issues in [c.strings].
+View all issues with WP status.
+Discussion:
+C99, and presumably amendment 1 to C90, specify that <wchar.h> +declares struct tm as an incomplete type. However, table 48 in 21.5 +[c.strings] does not mention the type tm as being declared in +<cwchar>. Is this omission intentional or accidental? +
+ + +Proposed resolution:
+In section 21.5 [c.strings], add "tm" to table 48.
+ + + + + +Section: 24.1 [iterator.requirements] Status: WP + Submitter: Jeremy Siek Date: 2001-10-20
+View other active issues in [iterator.requirements].
+View all other issues in [iterator.requirements].
+View all issues with WP status.
+Discussion:
+Iterator member functions and operators that do not change the state +of the iterator should be defined as const member functions or as +functions that take iterators either by const reference or by +value. The standard does not explicitly state which functions should +be const. Since this a fairly common mistake, the following changes +are suggested to make this explicit.
+ +The tables almost indicate constness properly through naming: r +for non-const and a,b for const iterators. The following changes +make this more explicit and also fix a couple problems.
+ + +Proposed resolution:
+In 24.1 [iterator.requirements] Change the first section of p9 from +"In the following sections, a and b denote values of X..." to +"In the following sections, a and b denote values of type const X...".
+ +In Table 73, change
+a->m U& ... ++ +
to
+ +a->m const U& ... + r->m U& ... ++ +
In Table 73 expression column, change
+ +*a = t ++ +
to
+ +*r = t ++ +
[Redmond: The container requirements should be reviewed to see if +the same problem appears there.]
+ + + + + + + +Section: 22.1.1.1.1 [locale.category] Status: WP + Submitter: P.J. Plauger, Nathan Myers Date: 2001-10-23
+View all other issues in [locale.category].
+View all issues with WP status.
+Discussion:
++In 22.1.1.1.1 [locale.category] paragraph 1, the category members +are described as bitmask elements. In fact, the bitmask requirements +in 17.3.2.1.2 [bitmask.types] don't seem quite right: none +and all are bitmask constants, not bitmask elements.
+ +In particular, the requirements for none interact poorly +with the requirement that the LC_* constants from the C library must +be recognizable as C++ locale category constants. LC_* values should +not be mixed with these values to make category values.
+ +We have two options for the proposed resolution. Informally: +option 1 removes the requirement that LC_* values be recognized as +category arguments. Option 2 changes the category type so that this +requirement is implementable, by allowing none to be some +value such as 0x1000 instead of 0.
+ +Nathan writes: "I believe my proposed resolution [Option 2] merely +re-expresses the status quo more clearly, without introducing any +changes beyond resolving the DR.
+ + + +Proposed resolution:
+Replace the first two paragraphs of 22.1.1.1 [locale.types] with:
+++typedef int category; ++ +Valid category values include the locale member bitmask +elements collate, ctype, monetary, +numeric, time, and messages, each of which +represents a single locale category. In addition, locale member +bitmask constant none is defined as zero and represents no +category. And locale member bitmask constant all is defined such that +the expression
+(collate | ctype | monetary | numeric | time | messages | all) == all +++is true, and represents the union of all categories. Further +the expression (X | Y), where X and Y each +represent a single category, represents the union of the two +categories. +
+ ++locale member functions expecting a category +argument require one of the category values defined above, or +the union of two or more such values. Such a category +argument identifies a set of locale categories. Each locale category, +in turn, identifies a set of locale facets, including at least those +shown in Table 51: +
+
[Curaçao: need input from locale experts.]
+ + + + +Rationale:
+ +The LWG considered, and rejected, an alternate proposal (described + as "Option 2" in the discussion). The main reason for rejecting it + was that library implementors were concerened about implementation + difficult, given that getting a C++ library to work smoothly with a + separately written C library is already a delicate business. Some + library implementers were also concerned about the issue of adding + extra locale categories.
+ +++ + + + + +Option 2:
+
+Replace the first paragraph of 22.1.1.1 [locale.types] with:+++Valid category values include the enumerated values. In addition, the +result of applying commutative operators | and & to any two valid +values is valid, and results in the setwise union and intersection, +respectively, of the argument categories. The values all and +none are defined such that for any valid value cat, the +expressions (cat | all == all), (cat & all == cat), +(cat | none == cat) and (cat & none == none) are +true. For non-equal values cat1 and cat2 of the +remaining enumerated values, (cat1 & cat2 == none) is true. +For any valid categories cat1 and cat2, the result +of (cat1 & ~cat2) is valid, and equals the setwise union of +those categories found in cat1 but not found in cat2. +[Footnote: it is not required that all equal the setwise union +of the other enumerated values; implementations may add extra categories.] +
+
Section: 24.5.2 [ostream.iterator] Status: WP + Submitter: Andy Sawyer Date: 2001-10-24
+View all issues with WP status.
+Discussion:
+24.5.2 [lib.ostream.iterator] states:
+[...] + + private: + // basic_ostream<charT,traits>* out_stream; exposition only + // const char* delim; exposition only ++ +
Whilst it's clearly marked "exposition only", I suspect 'delim' +should be of type 'const charT*'.
+ + +Proposed resolution:
++In 24.5.2 [ostream.iterator], replace const char* delim with +const charT* delim. +
+ + + + + +Section: 21.1.2 [char.traits.typedefs] Status: WP + Submitter: Martin Sebor Date: 2001-12-02
+View all issues with WP status.
+Discussion:
++(1) +There are no requirements on the stateT template parameter of +fpos listed in 27.4.3. The interface appears to require that +the type be at least Assignable and CopyConstructible (27.4.3.1, p1), +and I think also DefaultConstructible (to implement the operations in +Table 88). +
++21.1.2, p3, however, only requires that +char_traits<charT>::state_type meet the requirements of +CopyConstructible types. +
++(2) +Additionally, the stateT template argument has no +corresponding typedef in fpos which might make it difficult to use in +generic code. +
+ + +Proposed resolution:
++Modify 21.1.2, p4 from +
++ Requires: state_type shall meet the requirements of + CopyConstructible types (20.1.3). +
++ Requires: state_type shall meet the requirements of Assignable + (23.1, p4), CopyConstructible (20.1.3), and + DefaultConstructible (20.1.4) types. +
+ + + +Rationale:
+The LWG feels this is two issues, as indicated above. The first is +a defect---std::basic_fstream is unimplementable without these +additional requirements---and the proposed resolution fixes it. The +second is questionable; who would use that typedef? The class +template fpos is used only in a very few places, all of which know the +state type already. Unless motivation is provided, the second should +be considered NAD.
+ + + + + +Section: 23.1.4 [associative.reqmts] Status: WP + Submitter: Hans Aberg Date: 2001-12-17
+View all other issues in [associative.reqmts].
+View all issues with WP status.
+Discussion:
++Discussions in the thread "Associative container lower/upper bound +requirements" on comp.std.c++ suggests that there is a defect in the +C++ standard, Table 69 of section 23.1.2, "Associative containers", +[lib.associative.reqmts]. It currently says:
+ +++ ++a.find(k): returns an iterator pointing to an element with the key equivalent to +k, or a.end() if such an element is not found. +
+ ++a.lower_bound(k): returns an iterator pointing to the first element with +key not less than k. +
+ ++a.upper_bound(k): returns an iterator pointing to the first element with +key greater than k. +
+
+We have "or a.end() if such an element is not found" for +find, but not for upper_bound or +lower_bound. As the text stands, one would be forced to +insert a new element into the container and return an iterator to that +in case the sought iterator does not exist, which does not seem to be +the intention (and not possible with the "const" versions). +
+ + +Proposed resolution:
+ +Change Table 69 of section 23.1.4 [associative.reqmts] indicated entries +to:
+ +++ ++a.lower_bound(k): returns an iterator pointing to the first element with +key not less than k, or a.end() if such an element is not found. +
+ ++a.upper_bound(k): returns an iterator pointing to the first element with +key greater than k, or a.end() if such an element is not found. +
+
[Curaçao: LWG reviewed PR.]
+ + + + + + + + +Section: 23.1.3 [sequence.reqmts] Status: WP + Submitter: Yaroslav Mironov Date: 2002-01-23
+View all other issues in [sequence.reqmts].
+View all issues with WP status.
+Discussion:
+ +Table 68 "Optional Sequence Operations" in 23.1.1/12 +specifies operational semantics for "a.back()" as +"*--a.end()", which may be ill-formed [because calling +operator-- on a temporary (the return) of a built-in type is +ill-formed], provided a.end() returns a simple pointer rvalue +(this is almost always the case for std::vector::end(), for +example). Thus, the specification is not only incorrect, it +demonstrates a dangerous construct: "--a.end()" may +successfully compile and run as intended, but after changing the type +of the container or the mode of compilation it may produce +compile-time error.
+ + + +Proposed resolution:
+Change the specification in table 68 "Optional Sequence +Operations" in 23.1.1/12 for "a.back()" from
+ + ++ +*--a.end() +
to
+ ++ +{ iterator tmp = a.end(); --tmp; return *tmp; } +
and the specification for "a.pop_back()" from
+ ++ +a.erase(--a.end()) +
to
+ ++ +{ iterator tmp = a.end(); --tmp; a.erase(tmp); } +
[Curaçao: LWG changed PR from "{ X::iterator tmp = +a.end(); return *--tmp; }" to "*a.rbegin()", and from +"{ X::iterator tmp = a.end(); a.erase(--tmp); }" to +"a.erase(rbegin())".]
+ + +[There is a second possible defect; table 68 "Optional +Sequence Operations" in the "Operational Semantics" +column uses operations present only in the "Reversible +Container" requirements, yet there is no stated dependency +between these separate requirements tables. Ask in Santa Cruz if the +LWG would like a new issue opened.]
+ + +[Santa Cruz: the proposed resolution is even worse than what's in + the current standard: erase is undefined for reverse iterator. If + we're going to make the change, we need to define a temporary and + use operator--. Additionally, we don't know how prevalent this is: + do we need to make this change in more than one place? Martin has + volunteered to review the standard and see if this problem occurs + elsewhere.]
+ + +[Oxford: Matt provided new wording to address the concerns raised + in Santa Cruz. It does not appear that this problem appears + anywhere else in clauses 23 or 24.]
+ + +[Kona: In definition of operational semantics of back(), change +"*tmp" to "return *tmp;"]
+ + + + + + + +Section: 22.2.2.1.2 [facet.num.get.virtuals] Status: WP + Submitter: Martin Sebor Date: 2002-03-12
+View other active issues in [facet.num.get.virtuals].
+View all other issues in [facet.num.get.virtuals].
+View all issues with WP status.
+Discussion:
++I don't think thousands_sep is being treated correctly after +decimal_point has been seen. Since grouping applies only to the +integral part of the number, the first such occurrence should, IMO, +terminate Stage 2. (If it does not terminate it, then 22.2.2.1.2, p12 +and 22.2.3.1.2, p3 need to explain how thousands_sep is to be +interpreted in the fractional part of a number.) +
+ ++The easiest change I can think of that resolves this issue would be +something like below. +
+ + +Proposed resolution:
++Change the first sentence of 22.2.2.1.2, p9 from +
+ ++ ++ If discard is true then the position of the character is + remembered, but the character is otherwise ignored. If it is not + discarded, then a check is made to determine if c is allowed as + the next character of an input field of the conversion specifier + returned by stage 1. If so it is accumulated. +
to
+ ++ + + ++ If discard is true, then if '.' has not yet been + accumulated, then the position of the character is remembered, but + the character is otherwise ignored. Otherwise, if '.' has + already been accumulated, the character is discarded and Stage 2 + terminates. ... +
Rationale:
+We believe this reflects the intent of the Standard. Thousands sep + characters after the decimal point are not useful in any locale. + Some formatting conventions do group digits that follow the decimal + point, but they usually introduce a different grouping character + instead of reusing the thousand sep character. If we want to add + support for such conventions, we need to do so explicitly.
+ + + + + + +Section: 22.2.2.2.1 [facet.num.put.members] Status: WP + Submitter: Martin Sebor Date: 2002-03-12
+View all issues with WP status.
+Discussion:
+22.2.2.2.1, p1:
+ +iter_type put (iter_type out, ios_base& str, char_type fill, + bool val) const; + ... + + 1 Returns: do_put (out, str, fill, val). ++ +
AFAICS, the behavior of do_put (..., bool) is not documented anywhere, +however, 22.2.2.2.2, p23:
+ +++ +iter_type put (iter_type out, ios_base& str, char_type fill, + bool val) const; ++ + +Effects: If (str.flags() & ios_base::boolalpha) == 0 then do + out = do_put(out, str, fill, (int)val) + Otherwise do
+string_type s = + val ? use_facet<ctype<charT> >(loc).truename() + : use_facet<ctype<charT> >(loc).falsename(); ++and then insert the characters of s into out. out.
+
+This means that the bool overload of do_put() will never be called, +which contradicts the first paragraph. Perhaps the declaration +should read do_put(), and not put()? +
+ ++Note also that there is no Returns clause for this function, which +should probably be corrected, just as should the second occurrence +of "out." in the text. +
+ ++I think the least invasive change to fix it would be something like +the following: +
+ + +Proposed resolution:
+In 22.2.2.2.2 [facet.num.put.virtuals], just above paragraph 1, remove + the bool overload.
+ ++In 22.2.2.2.2 [facet.num.put.virtuals], p23, make the following changes +
+ ++ ++ Replace put() with do_put() in the declaration + of the member function. +
+ ++ Change the Effects clause to a Returns clause (to + avoid the requirement to call do_put(..., int) from + do_put (..., bool)) + like so: +
+ + + ++ 23 Returns: If (str.flags() & + ios_base::boolalpha) == 0 then + do_put (out, str, fill, (long)val) + Otherwise the function obtains a string s as if by
+string_type s = + val ? use_facet<ctype<charT> >(loc).truename() + : use_facet<ctype<charT> >(loc).falsename(); ++and then inserts each character c of s into out via + *out++ = c + and returns out.
+
Rationale:
+This fixes a couple of obvious typos, and also fixes what appears to +be a requirement of gratuitous inefficiency. +
+ + + + +Section: 22.1.1 [locale] Status: WP + Submitter: Martin Sebor Date: 2002-03-12
+View all other issues in [locale].
+View all issues with WP status.
+Discussion:
++22.1.1, p7 (copied below) allows iostream formatters and extractors +to make assumptions about the values returned from facet members. +However, such assumptions are apparently not guaranteed to hold +in other cases (e.g., when the facet members are being called directly +rather than as a result of iostream calls, or between successive +calls to the same iostream functions with no interevening calls to +imbue(), or even when the facet member functions are called +from other member functions of other facets). This restriction +prevents locale from being implemented efficiently. +
+ + +Proposed resolution:
+Change the first sentence in 22.1.1, p7 from
++ ++ In successive calls to a locale facet member function during + a call to an iostream inserter or extractor or a streambuf member + function, the returned result shall be identical. [Note: This + implies that such results may safely be reused without calling + the locale facet member function again, and that member functions + of iostream classes cannot safely call imbue() + themselves, except as specified elsewhere. --end note] +
to
+ ++ + + ++ In successive calls to a locale facet member function on a facet + object installed in the same locale, the returned result shall be + identical. ... +
Rationale:
+This change is reasonable becuase it clarifies the intent of this + part of the standard.
+ + + + + +Section: D.8 [depr.lib.binders] Status: WP + Submitter: Andrew Demkin Date: 2002-04-26
+View all other issues in [depr.lib.binders].
+View all issues with WP status.
+Discussion:
++The definition of bind1st() (D.8 [depr.lib.binders]) can result in +the construction of an unsafe binding between incompatible pointer +types. For example, given a function whose first parameter type is +'pointer to T', it's possible without error to bind an argument of +type 'pointer to U' when U does not derive from T: +
+foo(T*, int); + + struct T {}; + struct U {}; + + U u; + + int* p; + int* q; + + for_each(p, q, bind1st(ptr_fun(foo), &u)); // unsafe binding ++ +
+The definition of bind1st() includes a functional-style conversion to +map its argument to the expected argument type of the bound function +(see below): +
+typename Operation::first_argument_type(x) ++ +
A functional-style conversion (D.8 [depr.lib.binders]) is defined to +be +semantically equivalent to an explicit cast expression (D.8 +[depr.lib.binders]), which may (according to 5.4, paragraph 5) be +interpreted +as a reinterpret_cast, thus masking the error. +
+ +The problem and proposed change also apply to D.8 [depr.lib.binders].
+ + +Proposed resolution:
+Add this sentence to the end of D.8 [depr.lib.binders]/1: + "Binders bind1st and bind2nd are deprecated in + favor of std::tr1::bind."
+ +(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.5.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.4.2.1.1 [ios::failure] Status: WP + Submitter: Walter Brown and Marc Paterno Date: 2002-05-20
+View all other issues in [ios::failure].
+View all issues with WP status.
+Discussion:
++The destructor of ios_base::failure should have an empty throw +specification, because the destructor of its base class, exception, is +declared in this way. +
+ + +Proposed resolution:
+Change the destructor to
+virtual ~failure() throw(); ++ + +
Rationale:
+Fixes an obvious glitch. This is almost editorial.
+ + + + + +Section: 27.5.2.4.2 [streambuf.virt.buffer] Status: WP + Submitter: Walter Brown, Marc Paterno Date: 2002-05-10
+View all other issues in [streambuf.virt.buffer].
+View all issues with WP status.
+Discussion:
++27.5.2.4.2 [streambuf.virt.buffer] paragraph 1 is inconsistent with the Effects +clause for seekoff. +
+ + +Proposed resolution:
++Make this paragraph, the Effects clause for setbuf, consistent in wording +with the Effects clause for seekoff in paragraph 3 by amending paragraph 1 +to indicate the purpose of setbuf: +
+ +Original text:
+ ++ ++1 Effects: Performs an operation that is defined separately for each +class derived from basic_streambuf in this clause (27.7.1.3, 27.8.1.4). +
Proposed text:
+ ++ + + ++1 Effects: Influences stream buffering in a way that is defined separately +for each class derived from basic_streambuf in this clause +(27.7.1.3, 27.8.1.4). +
Rationale:
+The LWG doesn't believe there is any normative difference between + the existing wording and what's in the proposed resolution, but the + change may make the intent clearer.
+ + + + + +Section: 27 [input.output] Status: WP + Submitter: Walter Brown, Marc Paterno Date: 2002-05-10
+View all other issues in [input.output].
+View all issues with WP status.
+Discussion:
++Some stream and streambuf member functions are declared non-const, +even thought they appear only to report information rather than to +change an object's logical state. They should be declared const. See +document N1360 for details and rationale. +
+ +The list of member functions under discussion: in_avail, +showmanyc, tellg, tellp, is_open.
+ +Related issue: 73
+ + + +Proposed resolution:
+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
+bool is_open(); ++
with
+bool is_open() const; ++ + +
Rationale:
+Of the changes proposed in N1360, the only one that is safe is +changing the filestreams' is_open to const. The LWG believed that +this was NAD the first time it considered this issue (issue 73), but now thinks otherwise. The corresponding streambuf +member function, after all,is already const.
+ +The other proposed changes are less safe, because some streambuf +functions that appear merely to report a value do actually perform +mutating operations. It's not even clear that they should be +considered "logically const", because streambuf has two interfaces, a +public one and a protected one. These functions may, and often do, +change the state as exposed by the protected interface, even if the +state exposed by the public interface is unchanged.
+ +Note that implementers can make this change in a binary compatible +way by providing both overloads; this would be a conforming extension.
+ + + + + + +Section: 27.3 [iostream.objects] Status: WP + Submitter: Ruslan Abdikeev Date: 2002-07-08
+View all other issues in [iostream.objects].
+View all issues with WP status.
+Discussion:
++Is it safe to use standard iostream objects from constructors of +static objects? Are standard iostream objects constructed and are +their associations established at that time? +
+ +Surpisingly enough, Standard does NOT require that.
+ ++27.3/2 [lib.iostream.objects] guarantees that standard iostream +objects are constructed and their associations are established before +the body of main() begins execution. It also refers to ios_base::Init +class as the panacea for constructors of static objects. +
+ ++However, there's nothing in 27.3 [lib.iostream.objects], +in 27.4.2 [lib.ios.base], and in 27.4.2.1.6 [lib.ios::Init], +that would require implementations to allow access to standard +iostream objects from constructors of static objects. +
+ +Details:
+ +Core text refers to some magic object ios_base::Init, which will +be discussed below:
+ ++ ++ "The [standard iostream] objects are constructed, and their + associations are established at some time prior to or during + first time an object of class basic_ios<charT,traits>::Init + is constructed, and in any case before the body of main + begins execution." (27.3/2 [lib.iostream.objects]) +
+The first non-normative footnote encourages implementations +to initialize standard iostream objects earlier than required. +
+ +However, the second non-normative footnote makes an explicit +and unsupported claim:
+ ++ ++ "Constructors and destructors for static objects can access these + [standard iostream] objects to read input from stdin or write output + to stdout or stderr." (27.3/2 footnote 265 [lib.iostream.objects]) +
+The only bit of magic is related to that ios_base::Init class. AFAIK, +the rationale behind ios_base::Init was to bring an instance of this +class to each translation unit which #included <iostream> or +related header. Such an inclusion would support the claim of footnote +quoted above, because in order to use some standard iostream object it +is necessary to #include <iostream>. +
+ ++However, while Standard explicitly describes ios_base::Init as +an appropriate class for doing the trick, I failed to found a +mention of an _instance_ of ios_base::Init in Standard. +
+ + +Proposed resolution:
+ +Add to 27.3 [iostream.objects], p2, immediately before the last sentence +of the paragraph, the following two sentences:
+ ++ ++If a translation unit includes <iostream>, or explicitly +constructs an ios_base::Init object, these stream objects shall +be constructed before dynamic initialization of non-local +objects defined later in that translation unit, and these stream +objects shall be destroyed after the destruction of dynamically +initialized non-local objects defined later in that translation unit. +
[Lillehammer: Matt provided wording.]
+ +[Mont Tremblant: Matt provided revised wording.]
+ + + +Rationale:
++The original proposed resolution unconditionally required +implementations to define an ios_base::Init object of some +implementation-defined name in the header <iostream>. That's an +overspecification. First, defining the object may be unnecessary +and even detrimental to performance if an implementation can +guarantee that the 8 standard iostream objects will be initialized +before any other user-defined object in a program. Second, there +is no need to require implementations to document the name of the +object.
+ ++The new proposed resolution gives users guidance on what they need to +do to ensure that stream objects are constructed during startup.
+ + + + + +Section: 27.6.1.3 [istream.unformatted] Status: WP + Submitter: Ray Lischner Date: 2002-07-15
+View all other issues in [istream.unformatted].
+View all issues with WP status.
+Discussion:
+Defect report for description of basic_istream::get (section +27.6.1.3 [istream.unformatted]), paragraph 15. The description for the +get function +with the following signature:
+ +basic_istream<charT,traits>& get(basic_streambuf<char_type,traits>& + sb); ++ +
is incorrect. It reads
+ ++ ++ Effects: Calls get(s,n,widen('\n')) +
which I believe should be:
+ ++ + ++ Effects: Calls get(sb,widen('\n')) +
Proposed resolution:
+Change the Effects paragraph to:
++ ++ Effects: Calls get(sb,this->widen('\n')) +
[Pre-Oxford: Minor correction from Howard: replaced 'widen' + with 'this->widen'.]
+ + + + +Rationale:
Fixes an obvious typo.
+ + + + +Section: 23.1 [container.requirements] Status: WP + Submitter: Frank Compagner Date: 2002-07-20
+View other active issues in [container.requirements].
+View all other issues in [container.requirements].
+View all issues with WP status.
+Discussion:
++The requirements for multiset and multimap containers (23.1 +[lib.containers.requirements], 23.1.2 [lib.associative.reqmnts], +23.3.2 [lib.multimap] and 23.3.4 [lib.multiset]) make no mention of +the stability of the required (mutating) member functions. It appears +the standard allows these functions to reorder equivalent elements of +the container at will, yet the pervasive red-black tree implementation +appears to provide stable behaviour. +
+ +This is of most concern when considering the behaviour of erase(). +A stability requirement would guarantee the correct working of the +following 'idiom' that removes elements based on a certain predicate +function. +
+ +multimap<int, int> m; + multimap<int, int>::iterator i = m.begin(); + while (i != m.end()) { + if (pred(i)) + m.erase (i++); + else + ++i; + } ++ +
+Although clause 23.1.2/8 guarantees that i remains a valid iterator +througout this loop, absence of the stability requirement could +potentially result in elements being skipped. This would make +this code incorrect, and, furthermore, means that there is no way +of erasing these elements without iterating first over the entire +container, and second over the elements to be erased. This would +be unfortunate, and have a negative impact on both performance and +code simplicity. +
+ ++If the stability requirement is intended, it should be made explicit +(probably through an extra paragraph in clause 23.1.2). +
++If it turns out stability cannot be guaranteed, i'd argue that a +remark or footnote is called for (also somewhere in clause 23.1.2) to +warn against relying on stable behaviour (as demonstrated by the code +above). If most implementations will display stable behaviour, any +problems emerging on an implementation without stable behaviour will +be hard to track down by users. This would also make the need for an +erase_if() member function that much greater. +
+ +This issue is somewhat related to LWG issue 130.
+ + + +Proposed resolution:
+ +Add the following to the end of 23.1.4 [associative.reqmts] paragraph 4: +"For multiset and multimap, 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.]
+ + +[Mont Tremblant: Changed set and map to multiset and multimap.]
+ + + + +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.6.1.2.1 [istream.formatted.reqmts], 27.6.2.6.1 [ostream.formatted.reqmts] Status: WP + Submitter: Keith Baker Date: 2002-07-23
+View all other issues in [istream.formatted.reqmts].
+View all issues with WP status.
+Discussion:
+ ++In 27.6.1.2.1 [istream.formatted.reqmts] and 27.6.2.6.1 [ostream.formatted.reqmts] +(exception()&badbit) != 0 is used in testing for rethrow, yet +exception() is the constructor to class std::exception in 18.6.1 [type.info] that has no return type. Should member function +exceptions() found in 27.4.4 [ios] be used instead? +
+ + + +Proposed resolution:
++In 27.6.1.2.1 [istream.formatted.reqmts] and 27.6.2.6.1 [ostream.formatted.reqmts], change +"(exception()&badbit) != 0" to "(exceptions()&badbit) != 0". +
+ + +Rationale:
+Fixes an obvious typo.
+ + + + + +Section: 27.7.1.4 [stringbuf.virtuals] Status: WP + Submitter: Ray Lischner Date: 2002-08-14
+View all other issues in [stringbuf.virtuals].
+View all issues with WP status.
+Discussion:
++In Section 27.7.1.4 [stringbuf.virtuals]: Table 90, Table 91, and paragraph +14 all contain references to "basic_ios::" which should be +"ios_base::". +
+ + +Proposed resolution:
++Change all references to "basic_ios" in Table 90, Table 91, and +paragraph 14 to "ios_base". +
+ + +Rationale:
Fixes an obvious typo.
+ + + + +Section: 27.7.1.4 [stringbuf.virtuals] Status: WP + Submitter: Ray Lischner Date: 2002-08-14
+View all other issues in [stringbuf.virtuals].
+View all issues with WP status.
+Discussion:
++In Section 27.7.1.4 [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.
+ ++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 +
+ ++ (which & (ios_base::in|ios_base::out)) == ios_base::out +
+ ++ (which & (ios_base::in|ios_base::out)) == +(ios_base::in|ios_base::out) + and way == either ios_base::beg or ios_base::end +
+ +Otherwise
+
Rationale:
+It's clear what we wanted to say, we just failed to say it. This + fixes it.
+ + + + + +Section: 22.2.1.1.2 [locale.ctype.virtuals] Status: WP + Submitter: Martin Sebor Date: 2002-09-06
+View all other issues in [locale.ctype.virtuals].
+View all issues with WP status.
+Discussion:
++The last sentence in 22.2.1.1.2, p11 below doesn't seem to make sense. +
+charT do_widen (char c) const; + + -11- Effects: Applies the simplest reasonable transformation from + a char value or sequence of char values to the corresponding + charT value or values. The only characters for which unique + transformations are required are those in the basic source + character set (2.2). For any named ctype category with a + ctype<charT> facet ctw and valid ctype_base::mask value + M (is(M, c) || !ctw.is(M, do_widen(c))) is true. ++
+Shouldn't the last sentence instead read +
+For any named ctype category with a ctype<char> facet ctc + and valid ctype_base::mask value M + (ctc.is(M, c) || !is(M, do_widen(c))) is true. ++
+I.e., if the narrow character c is not a member of a class of +characters then neither is the widened form of c. (To paraphrase +footnote 224.) +
+ + +Proposed resolution:
++Replace the last sentence of 22.2.1.1.2 [locale.ctype.virtuals], p11 with the +following text: +
+For any named ctype category with a ctype<char> facet ctc + and valid ctype_base::mask value M, + (ctc.is(M, c) || !is(M, do_widen(c))) is true. ++ +
[Kona: Minor edit. Added a comma after the M for clarity.]
+ + + + +Rationale:
+The LWG believes this is just a typo, and that this is the correct fix.
+ + + + + +Section: 22.2.1.5 [locale.codecvt.byname] Status: WP + Submitter: Martin Sebor Date: 2002-09-06
+View all other issues in [locale.codecvt.byname].
+View all issues with WP status.
+Discussion:
++Tables 53 and 54 in 22.2.1.5 [locale.codecvt.byname] are both titled "convert +result values," when surely "do_in/do_out result values" must have +been intended for Table 53 and "do_unshift result values" for Table +54. +
++Table 54, row 3 says that the meaning of partial is "more characters +needed to be supplied to complete termination." The function is not +supplied any characters, it is given a buffer which it fills with +characters or, more precisely, destination elements (i.e., an escape +sequence). So partial means that space for more than (to_limit - to) +destination elements was needed to terminate a sequence given the +value of state. +
+ + +Proposed resolution:
++Change the title of Table 53 to "do_in/do_out result values" and +the title of Table 54 to "do_unshift result values." +
++Change the text in Table 54, row 3 (the partial row), under the +heading Meaning, to "space for more than (to_limit - to) destination +elements was needed to terminate a sequence given the value of state." +
+ + + + +Section: 22.2.1.5 [locale.codecvt.byname] Status: WP + Submitter: Martin Sebor Date: 2002-09-06
+View all other issues in [locale.codecvt.byname].
+View all issues with WP status.
+Discussion:
++All but one codecvt member functions that take a state_type argument +list as one of their preconditions that the state_type argument have +a valid value. However, according to 22.2.1.5.2, p6, +codecvt::do_unshift() is the only codecvt member that is supposed to +return error if the state_type object is invalid. +
+ ++It seems to me that the treatment of state_type by all codecvt member +functions should be the same and the current requirements should be +changed. Since the detection of invalid state_type values may be +difficult in general or computationally expensive in some specific +cases, I propose the following: +
+ + +Proposed resolution:
++Add a new paragraph before 22.2.1.5.2, p5, and after the function +declaration below +
+result do_unshift(stateT& state, + externT* to, externT* to_limit, externT*& to_next) const; ++
+as follows: +
+Requires: (to <= to_end) well defined and true; state initialized, + if at the beginning of a sequence, or else equal to the result of + converting the preceding characters in the sequence. ++
+and change the text in Table 54, row 4, the error row, under +the heading Meaning, from +
+state has invalid value ++
+to +
+an unspecified error has occurred ++ + +
Rationale:
+The intent is that implementations should not be required to detect +invalid state values; such a requirement appears nowhere else. An +invalid state value is a precondition violation, i.e. undefined +behavior. Implementations that do choose to detect invalid state +values, or that choose to detect any other kind of error, may return +error as an indication.
+ + + + + +Section: 24.1.4 [bidirectional.iterators] Status: WP + Submitter: ysapir (submitted via comp.std.c++) Date: 2002-10-17
+View all other issues in [bidirectional.iterators].
+View all issues with WP status.
+Discussion:
++Following a discussion on the boost list regarding end iterators and +the possibility of performing operator--() on them, it seems to me +that there is a typo in the standard. This typo has nothing to do +with that discussion. +
+ ++I have checked this newsgroup, as well as attempted a search of the +Active/Defect/Closed Issues List on the site for the words "s is +derefer" so I believe this has not been proposed before. Furthermore, +the "Lists by Index" mentions only DR 299 on section +24.1.4, and DR 299 is not related to this issue. +
+ ++The standard makes the following assertion on bidirectional iterators, +in section 24.1.4 [lib.bidirectional.iterators], Table 75: +
+ +operational assertion/note +expression return type semantics pre/post-condition + +--r X& pre: there exists s such + that r == ++s. + post: s is dereferenceable. + --(++r) == r. + --r == --s implies r == s. + &r == &--r. ++ +
+(See http://aspn.activestate.com/ASPN/Mail/Message/boost/1395763.) +
+ ++In particular, "s is dereferenceable" seems to be in error. It seems +that the intention was to say "r is dereferenceable". +
+ ++If it were to say "r is dereferenceable" it would +make perfect sense. Since s must be dereferenceable prior to +operator++, then the natural result of operator-- (to undo operator++) +would be to make r dereferenceable. Furthermore, without other +assertions, and basing only on precondition and postconditions, we +could not otherwise know this. So it is also interesting information. +
+ + + +Proposed resolution:
++Change the guarantee to "postcondition: r is dereferenceable." +
+ + +Rationale:
Fixes an obvious typo
+ + + + +Section: 25.3.3.3 [equal.range] Status: WP + Submitter: Hans Bos Date: 2002-10-18
+View all other issues in [equal.range].
+View all issues with WP status.
+Discussion:
++Section 25.3.3.3 [equal.range] +states that at most 2 * log(last - first) + 1 +comparisons are allowed for equal_range. +
+ +It is not possible to implement equal_range with these constraints.
+ +In a range of one element as in:
+int x = 1; + equal_range(&x, &x + 1, 1) ++ +
it is easy to see that at least 2 comparison operations are needed.
+ +For this case at most 2 * log(1) + 1 = 1 comparison is allowed.
+ +I have checked a few libraries and they all use the same (nonconforming) +algorithm for equal_range that has a complexity of
+2* log(distance(first, last)) + 2. ++
I guess this is the algorithm that the standard assumes for equal_range.
+ ++It is easy to see that 2 * log(distance) + 2 comparisons are enough +since equal range can be implemented with lower_bound and upper_bound +(both log(distance) + 1). +
+ ++I think it is better to require something like 2log(distance) + O(1) (or +even logarithmic as multiset::equal_range). +Then an implementation has more room to optimize for certain cases (e.g. +have log(distance) characteristics when at most match is found in the range +but 2log(distance) + 4 for the worst case). +
+ + + +Proposed resolution:
+In 25.3.3.1 [lower.bound]/4, change log(last - first) + 1 +to log2(last - first) + O(1).
+ +In 25.3.3.2 [upper.bound]/4, change log(last - first) + 1 +to log2(last - first) + O(1).
+ +In 25.3.3.3 [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: 24.4.1.3.11 [reverse.iter.op-=] Status: DR + Submitter: Matt Austern Date: 2002-10-23
+View all issues with DR status.
+Discussion:
+In 24.4.1.3.11 [reverse.iter.op-=], 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 [reverse.iter.requirements] change:
+ +++ +reference operator[](difference_type n) const; ++
to:
+ +++ + + + +unspecified operator[](difference_type n) const; // see 24.1.5 [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.5.2.3 [valarray.access] Status: WP + Submitter: Gabriel Dos Reis Date: 2002-11-08
+View all other issues in [valarray.access].
+View all issues with WP status.
+Duplicate of: 77
+Discussion:
+Consider the following program:
+#include <iostream> + #include <ostream> + #include <vector> + #include <valarray> + #include <algorithm> + #include <iterator> + template<typename Array> + void print(const Array& a) + { + using namespace std; + typedef typename Array::value_type T; + copy(&a[0], &a[0] + a.size(), + ostream_iterator<T>(std::cout, " ")); + } + template<typename T, unsigned N> + unsigned size(T(&)[N]) { return N; } + int main() + { + double array[] = { 0.89, 9.3, 7, 6.23 }; + std::vector<double> v(array, array + size(array)); + std::valarray<double> w(array, size(array)); + print(v); // #1 + std::cout << std::endl; + print(w); // #2 + std::cout << std::endl; + } ++ +
While the call numbered #1 succeeds, the call numbered #2 fails +because the const version of the member function +valarray<T>::operator[](size_t) returns a value instead of a +const-reference. That seems to be so for no apparent reason, no +benefit. Not only does that defeats users' expectation but it also +does hinder existing software (written either in C or Fortran) +integration within programs written in C++. There is no reason why +subscripting an expression of type valarray<T> that is const-qualified +should not return a const T&.
+ + +Proposed resolution:
+In the class synopsis in 26.5.2 [template.valarray], and in +26.5.2.3 [valarray.access] just above paragraph 1, change
+T operator[](size_t const); ++
to
+const T& operator[](size_t const); ++ +
[Kona: fixed a minor typo: put semicolon at the end of the line + wehre it belongs.]
+ + + + +Rationale:
+Return by value seems to serve no purpose. Valaray was explicitly +designed to have a specified layout so that it could easily be +integrated with libraries in other languages, and return by value +defeats that purpose. It is believed that this change will have no +impact on allowable optimizations.
+ + + + + +Section: 22.1.3.2 [conversions] Status: WP + Submitter: James Kanze Date: 2002-12-10
+View all issues with WP status.
+Discussion:
++The specifications of toupper and tolower both specify the functions as +const, althought they are not member functions, and are not specified as +const in the header file synopsis in section 22.1 [locales]. +
+ + +Proposed resolution:
+In 22.1.3.2 [conversions], remove const from the function + declarations of std::toupper and std::tolower
+ + +Rationale:
Fixes an obvious typo
+ + + + +Section: 26.7 [c.math] Status: WP + Submitter: James Kanze Date: 2003-01-03
+View all other issues in [c.math].
+View all issues with WP status.
+Discussion:
++In 26.7 [c.math], the C++ standard refers to the C standard for the +definition of rand(); in the C standard, it is written that "The +implementation shall behave as if no library function calls the rand +function." +
+ ++In 25.2.12 [alg.random.shuffle], there is no specification as to +how the two parameter version of the function generates its random +value. I believe that all current implementations in fact call rand() +(in contradiction with the requirement avove); if an implementation does +not call rand(), there is the question of how whatever random generator +it does use is seeded. Something is missing. +
+ + + +Proposed resolution:
++In [lib.c.math], add a paragraph specifying that the C definition of +rand shal be modified to say that "Unless otherwise specified, the +implementation shall behave as if no library function calls the rand +function." +
+ ++In [lib.alg.random.shuffle], add a sentence to the effect that "In +the two argument form of the function, the underlying source of +random numbers is implementation defined. [Note: in particular, an +implementation is permitted to use rand.] +
+ + +Rationale:
+The original proposed resolution proposed requiring the + two-argument from of random_shuffle to + use rand. We don't want to do that, because some existing + implementations already use something else: gcc + uses lrand48, for example. Using rand presents a + problem if the number of elements in the sequence is greater than + RAND_MAX.
+ + + + + +Section: 20.7.5.1 [allocator.members] Status: WP + Submitter: Markus Mauhart Date: 2003-02-27
+View all other issues in [allocator.members].
+View all issues with WP status.
+Discussion:
++20.7.5.1 [allocator.members] allocator members, contains +the following 3 lines: +
+ +12 Returns: new((void *) p) T( val) + void destroy(pointer p); + 13 Returns: ((T*) p)->~T() ++ +
+The type cast "(T*) p" in the last line is redundant cause +we know that std::allocator<T>::pointer is a typedef for T*. +
+ + +Proposed resolution:
++Replace "((T*) p)" with "p". +
+ + +Rationale:
Just a typo, this is really editorial.
+ + + + +Section: 20.1.2 [allocator.requirements] Status: WP + Submitter: Markus Mauhart Date: 2003-02-27
+View other active issues in [allocator.requirements].
+View all other issues in [allocator.requirements].
+View all issues with WP status.
+Discussion:
++I think that in par2 of [default.con.req] the last two +lines of table 32 contain two incorrect type casts. The lines are ... +
+ +a.construct(p,t) Effect: new((void*)p) T(t) + a.destroy(p) Effect: ((T*)p)?->~T() ++ +
+.... with the prerequisits coming from the preceding two paragraphs, especially +from table 31: +
+ +alloc<T> a ;// an allocator for T + alloc<T>::pointer p ;// random access iterator + // (may be different from T*) + alloc<T>::reference r = *p;// T& + T const& t ; ++ +
+For that two type casts ("(void*)p" and "(T*)p") to be well-formed +this would require then conversions to T* and void* for all +alloc<T>::pointer, so it would implicitely introduce extra +requirements for alloc<T>::pointer, additionally to the only +current requirement (being a random access iterator). +
+ + +Proposed resolution:
+ ++Accept proposed wording from +N2436 part 1. +
+ ++Note: Actually I would prefer to replace "((T*)p)?->dtor_name" with +"p?->dtor_name", but AFAICS this is not possible cause of an omission +in 13.5.6 [over.ref] (for which I have filed another DR on 29.11.2002). +
+ +[Kona: The LWG thinks this is somewhere on the border between + Open and NAD. The intend is clear: construct constructs an + object at the location p. It's reading too much into the + description to think that literally calling new is + required. Tweaking this description is low priority until we can do + a thorough review of allocators, and, in particular, allocators with + non-default pointer types.]
+ + +[ +Batavia: Proposed resolution changed to less code and more description. +]
+ + +[ +post Oxford: This would be rendered NAD Editorial by acceptance of +N2257. +]
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2387 for this issue which +was subsequently split out into a separate paper N2436 for the purposes of voting. +The resolution in N2436 addresses this issue. The LWG voted to accelerate this +issue to Ready status to be voted into the WP at Kona. +]
+ + + + + + + +Section: 20.1.2 [allocator.requirements], 20.7.5.1 [allocator.members] Status: WP + Submitter: Markus Mauhart Date: 2003-02-27
+View other active issues in [allocator.requirements].
+View all other issues in [allocator.requirements].
+View all issues with WP status.
+Discussion:
++This applies to the new expression that is contained in both par12 of +20.7.5.1 [allocator.members] and in par2 (table 32) of [default.con.req]. +I think this new expression is wrong, involving unintended side +effects. +
+ + +20.7.5.1 [allocator.members] contains the following 3 lines:
+ +11 Returns: the largest value N for which the call allocate(N,0) might succeed. + void construct(pointer p, const_reference val); + 12 Returns: new((void *) p) T( val) ++ + +
[default.con.req] in table 32 has the following line:
+a.construct(p,t) Effect: new((void*)p) T(t) ++ +
+.... with the prerequisits coming from the preceding two paragraphs, +especially from table 31: +
+ +alloc<T> a ;// an allocator for T + alloc<T>::pointer p ;// random access iterator + // (may be different from T*) + alloc<T>::reference r = *p;// T& + T const& t ; ++ +
+Cause of using "new" but not "::new", any existing "T::operator new" +function will hide the global placement new function. When there is no +"T::operator new" with adequate signature, +every_alloc<T>::construct(..) is ill-formed, and most +std::container<T,every_alloc<T>> use it; a workaround +would be adding placement new and delete functions with adequate +signature and semantic to class T, but class T might come from another +party. Maybe even worse is the case when T has placement new and +delete functions with adequate signature but with "unknown" semantic: +I dont like to speculate about it, but whoever implements +any_container<T,any_alloc> and wants to use construct(..) +probably must think about it. +
+ + +Proposed resolution:
++Replace "new" with "::new" in both cases. +
+ + + + + + + +Section: 21.3.6.8 [string::swap] Status: WP + Submitter: Beman Dawes Date: 2003-03-25
+View all other issues in [string::swap].
+View all issues with WP status.
+Discussion:
+ ++std::basic_string, 21.3 [basic.string] paragraph 2 says that +basic_string "conforms to the requirements of a Sequence, as specified +in (23.1.1)." The sequence requirements specified in (23.1.1) to not +include any prohibition on swap members throwing exceptions. +
+ ++Section 23.1 [container.requirements] paragraph 10 does limit conditions under +which exceptions may be thrown, but applies only to "all container +types defined in this clause" and so excludes basic_string::swap +because it is defined elsewhere. +
+ ++Eric Niebler points out that 21.3 [basic.string] paragraph 5 explicitly +permits basic_string::swap to invalidates iterators, which is +disallowed by 23.1 [container.requirements] paragraph 10. Thus the standard would +be contradictory if it were read or extended to read as having +basic_string meet 23.1 [container.requirements] paragraph 10 requirements. +
+ ++Yet several LWG members have expressed the belief that the original +intent was that basic_string::swap should not throw exceptions as +specified by 23.1 [container.requirements] paragraph 10, and that the standard is +unclear on this issue. The complexity of basic_string::swap is +specified as "constant time", indicating the intent was to avoid +copying (which could cause a bad_alloc or other exception). An +important use of swap is to ensure that exceptions are not thrown in +exception-safe code. +
+ ++Note: There remains long standing concern over whether or not it is +possible to reasonably meet the 23.1 [container.requirements] paragraph 10 swap +requirements when allocators are unequal. The specification of +basic_string::swap exception requirements is in no way intended to +address, prejudice, or otherwise impact that concern. +
+ + + + + + + +Proposed resolution:
++In 21.3.6.8 [string::swap], add a throws clause: +
+ ++Throws: Shall not throw exceptions. +
+ + + + + +Section: 17.4.3.5 [replacement.functions], 18.5.1 [new.delete] Status: WP + Submitter: Matt Austern Date: 2003-04-24
+View all issues with WP status.
+Discussion:
++The eight basic dynamic memory allocation functions (single-object +and array versions of ::operator new and ::operator delete, in the +ordinary and nothrow forms) are replaceable. A C++ program may +provide an alternative definition for any of them, which will be used +in preference to the implementation's definition. +
+ ++Three different parts of the standard mention requirements on +replacement functions: 17.4.3.5 [replacement.functions], 18.5.1.1 [new.delete.single] +and 18.5.1.2 [new.delete.array], and 3.7.2 [basic.stc.auto]. +
+ +None of these three places say whether a replacement function may + be declared inline. 18.5.1.1 [new.delete.single] paragraph 2 specifies a + signature for the replacement function, but that's not enough: + the inline specifier is not part of a function's signature. + One might also reason from 7.1.2 [dcl.fct.spec] paragraph 2, which + requires that "an inline function shall be defined in every + translation unit in which it is used," but this may not be quite + specific enough either. We should either explicitly allow or + explicitly forbid inline replacement memory allocation + functions.
+ + +Proposed resolution:
++Add a new sentence to the end of 17.4.3.5 [replacement.functions] paragraph 3: +"The program's definitions shall not be specified as inline. +No diagnostic is required." +
+ +[Kona: added "no diagnostic is required"]
+ + + + +Rationale:
++The fact that inline isn't mentioned appears to have been +nothing more than an oversight. Existing implementations do not +permit inline functions as replacement memory allocation functions. +Providing this functionality would be difficult in some cases, and is +believed to be of limited value. +
+ + + + + +Section: 25.4 [alg.c.library] Status: WP + Submitter: Ray Lischner Date: 2003-04-08
+View all other issues in [alg.c.library].
+View all issues with WP status.
+Discussion:
++Section 25.4 [alg.c.library] describes bsearch and qsort, from the C +standard library. Paragraph 4 does not list any restrictions on qsort, +but it should limit the base parameter to point to POD. Presumably, +qsort sorts the array by copying bytes, which requires POD. +
+ + +Proposed resolution:
++In 25.4 [alg.c.library] paragraph 4, just after the declarations and +before the nonnormative note, add these words: "both of which have the +same behavior as the original declaration. The behavior is undefined +unless the objects in the array pointed to by base are of POD +type." +
+ +[Something along these lines is clearly necessary. Matt + provided wording.]
+ + + + + + +Section: 23.2.6.4 [vector.modifiers] Status: DR + Submitter: Dave Abrahams Date: 2003-04-27
+View all other issues in [vector.modifiers].
+View all issues with DR status.
+Discussion:
++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.6.4 [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 [iterator.requirements] Status: WP + Submitter: Nathan Myers Date: 2003-06-03
+View other active issues in [iterator.requirements].
+View all other issues in [iterator.requirements].
+View all issues with WP status.
+Discussion:
++Clause 24.1 [iterator.requirements], paragraph 5, says that the only expression +that is defined for a singular iterator is "an assignment of a +non-singular value to an iterator that holds a singular value". This +means that destroying a singular iterator (e.g. letting an automatic +variable go out of scope) is technically undefined behavior. This +seems overly strict, and probably unintentional. +
+ + +Proposed resolution:
++Change the sentence in question to "... the only exceptions are +destroying an iterator that holds a singular value, or the assignment +of a non-singular value to an iterator that holds a singular value." +
+ + + + + +Section: 27.8.1.9 [ifstream.members], 27.8.1.13 [ofstream.members] Status: DR + Submitter: Nathan Myers Date: 2003-06-03
+View all other issues in [ifstream.members].
+View all issues with DR status.
+Discussion:
++A strict reading of 27.8.1 [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.9 [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.13 [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.17 [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: 23.2.4.1 [list.cons], 23.2.4.3 [list.modifiers] Status: WP + Submitter: Hans Bos Date: 2003-06-07
+View all other issues in [list.cons].
+View all issues with WP status.
+Discussion:
++Sections 23.2.4.1 [list.cons] and 23.2.4.3 [list.modifiers] list +comparison operators (==, !=, <, <=, >, =>) for queue and +stack. Only the semantics for queue::operator== (23.2.4.1 [list.cons] par2) and queue::operator< (23.2.4.1 [list.cons] +par3) are defined. +
+ + +Proposed resolution:
+ +Add the following new paragraphs after 23.2.4.1 [list.cons] + paragraph 3:
+ ++ ++ +operator!= ++Returns: x.c != y.c
+ +operator> ++Returns: x.c > y.c
+ +operator<= ++Returns: x.c <= y.c
+ +operator>= ++Returns: x.c >= y.c
+ +
Add the following paragraphs at the end of 23.2.4.3 [list.modifiers]:
+ ++ ++ + +operator== ++Returns: x.c == y.c
+ +operator< ++Returns: x.c < y.c
+ +operator!= ++Returns: x.c != y.c
+ +operator> ++Returns: x.c > y.c
+ +operator<= ++Returns: x.c <= y.c
+ +operator>= ++Returns: x.c >= y.c
+ +
[Kona: Matt provided wording.]
+ + + + +Rationale:
+There isn't any real doubt about what these operators are +supposed to do, but we ought to spell it out.
+ + + + + +Section: 25.3.5 [alg.set.operations] Status: WP + Submitter: Daniel Frey Date: 2003-07-09
+View all other issues in [alg.set.operations].
+View all issues with WP status.
+Discussion:
++25.3.5 [alg.set.operations] paragraph 1 reads: +"The semantics of the set operations are generalized to multisets in a +standard way by defining union() to contain the maximum number of +occurrences of every element, intersection() to contain the minimum, and +so on." +
+ ++This is wrong. The name of the functions are set_union() and +set_intersection(), not union() and intersection(). +
+ + +Proposed resolution:
+Change that sentence to use the correct names.
+ + + + + +Section: 27.4.4.3 [iostate.flags] Status: WP + Submitter: Martin Sebor Date: 2003-07-10
+View all other issues in [iostate.flags].
+View all issues with WP status.
+Duplicate of: 429
+Discussion:
++The Effects clause in 27.4.4.3 [iostate.flags] paragraph 5 says that the +function only throws if the respective bits are already set prior to +the function call. That's obviously not the intent. The typo ought to +be corrected and the text reworded as: "If (state & +exceptions()) == 0, returns. ..." +
+ + +Proposed resolution:
++In 27.4.4.3 [iostate.flags] paragraph 5, replace "If (rdstate() & +exceptions()) == 0" with "If ((state | (rdbuf() ? goodbit : badbit)) +& exceptions()) == 0". +
+ +[Kona: the original proposed resolution wasn't quite right. We + really do mean rdstate(); the ambiguity is that the wording in the + standard doesn't make it clear whether we mean rdstate() before + setting the new state, or rdsate() after setting it. We intend the + latter, of course. Post-Kona: Martin provided wording.]
+ + + + + + + +Section: 27.6.1.2.3 [istream::extractors] Status: DR + Submitter: Bo Persson Date: 2003-07-13
+View all other issues in [istream::extractors].
+View all issues with DR status.
+Discussion:
++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: 23.2.6.4 [vector.modifiers] Status: WP + Submitter: Matt Austern Date: 2003-08-19
+View all other issues in [vector.modifiers].
+View all issues with WP status.
+Discussion:
++Consider the following code fragment: +
+++ +int A[8] = { 1,3,5,7,9,8,4,2 }; +std::vector<int> v(A, A+8); + +std::vector<int>::iterator i1 = v.begin() + 3; +std::vector<int>::iterator i2 = v.begin() + 4; +v.erase(i1); ++
+Which iterators are invalidated by v.erase(i1): i1, i2, +both, or neither? +
+ ++On all existing implementations that I know of, the status of i1 and +i2 is the same: both of them will be iterators that point to some +elements of the vector (albeit not the same elements they did +before). You won't get a crash if you use them. Depending on +exactly what you mean by "invalidate", you might say that neither one +has been invalidated because they still point to something, +or you might say that both have been invalidated because in both +cases the elements they point to have been changed out from under the +iterator. +
+ ++The standard doesn't say either of those things. It says that erase +invalidates all iterators and references "after the point of the +erase". This doesn't include i1, since it's at the point of the +erase instead of after it. I can't think of any sensible definition +of invalidation by which one can say that i2 is invalidated but i1 +isn't. +
+ ++(This issue is important if you try to reason about iterator validity +based only on the guarantees in the standard, rather than reasoning +from typical implementation techniques. Strict debugging modes, +which some programmers find useful, do not use typical implementation +techniques.) +
+ + +Proposed resolution:
++In 23.2.6.4 [vector.modifiers] paragraph 3, change "Invalidates all the +iterators and references after the point of the erase" to +"Invalidates iterators and references at or after the point of the +erase". +
+ + +Rationale:
+I believe this was essentially a typographical error, and that it + was taken for granted that erasing an element invalidates iterators + that point to it. The effects clause in question treats iterators + and references in parallel, and it would seem counterintuitive to + say that a reference to an erased value remains valid.
+ + + + + +Section: 27.6.1.4 [istream.manip] Status: WP + Submitter: Martin Sebor Date: 2003-09-18
+View all issues with WP status.
+Discussion:
++According to 27.6.1.4, the ws() manipulator is not required to construct +the sentry object. The manipulator is also not a member function so the +text in 27.6.1, p1 through 4 that describes the exception policy for +istream member functions does not apply. That seems inconsistent with +the rest of extractors and all the other input functions (i.e., ws will +not cause a tied stream to be flushed before extraction, it doesn't check +the stream's exceptions or catch exceptions thrown during input, and it +doesn't affect the stream's gcount). +
+ + +Proposed resolution:
++Add to 27.6.1.4 [istream.manip], immediately before the first sentence +of paragraph 1, the following text: +
+ ++ ++ Behaves as an unformatted input function (as described in + 27.6.1.3, paragraph 1), except that it does not count the number + of characters extracted and does not affect the value returned by + subsequent calls to is.gcount(). After constructing a sentry + object... +
[Post-Kona: Martin provided wording]
+ + + + + + +Section: 18.2.2 [c.limits] Status: WP + Submitter: Martin Sebor Date: 2003-09-18
+View all issues with WP status.
+Discussion:
+
+
+Given two overloads of the function foo(), one taking an argument of type
+int and the other taking a long, which one will the call foo(LONG_MAX)
+resolve to? The expected answer should be foo(long), but whether that
+is true depends on the #defintion of the LONG_MAX macro, specifically
+its type. This issue is about the fact that the type of these macros
+is not actually required to be the same as the the type each respective
+limit.
+
+
+Section 18.2.2 of the C++ Standard does not specify the exact types of
+the XXX_MIN and XXX_MAX macros #defined in the <climits> and <limits.h>
+headers such as INT_MAX and LONG_MAX and instead defers to the C standard.
+
+
+Section 5.2.4.2.1, p1 of the C standard specifies that "The values [of
+these constants] shall be replaced by constant expressions suitable for use
+in #if preprocessing directives. Moreover, except for CHAR_BIT and MB_LEN_MAX,
+the following shall be replaced by expressions that have the same type as
+would an expression that is an object of the corresponding type converted
+according to the integer promotions."
+
+
+The "corresponding type converted according to the integer promotions" for
+LONG_MAX is, according to 6.4.4.1, p5 of the C standard, the type of long
+converted to the first of the following set of types that can represent it:
+int, long int, long long int. So on an implementation where (sizeof(long)
+== sizeof(int)) this type is actually int, while on an implementation where
+(sizeof(long) > sizeof(int)) holds this type will be long.
+
+
+This is not an issue in C since the type of the macro cannot be detected
+by any conforming C program, but it presents a portability problem in C++
+where the actual type is easily detectable by overload resolution.
+
+
[Kona: the LWG does not believe this is a defect. The C macro + definitions are what they are; we've got a better + mechanism, std::numeric_limits, that is specified more + precisely than the C limit macros. At most we should add a + nonnormative note recommending that users who care about the exact + types of limit quantities should use <limits> instead of + <climits>.]
+ + + + +Proposed resolution:
+ ++Change 18.2.2 [c.limits], paragraph 2: +
+ ++ + + + + ++-2- The contents are the same as the Standard C library header <limits.h>. +[Note: The types of the macros in <climits> are not guaranteed +to match the type to which they refer.--end note] +
Section: 27.8.1 [fstreams] Status: WP + Submitter: Martin Sebor Date: 2003-09-18
+View all other issues in [fstreams].
+View all issues with WP status.
+Discussion:
++7.19.1, p2, of C99 requires that the FILE type only be declared in +<stdio.h>. None of the (implementation-defined) members of the +struct is mentioned anywhere for obvious reasons. +
+ ++C++ says in 27.8.1, p2 that FILE is a type that's defined in <cstdio>. Is +it really the intent that FILE be a complete type or is an implementation +allowed to just declare it without providing a full definition? +
+ + +Proposed resolution:
+In the first sentence of 27.8.1 [fstreams] paragraph 2, change + "defined" to "declared".
+ + +Rationale:
+We don't want to impose any restrictions beyond what the C standard + already says. We don't want to make anything implementation defined, + because that imposes new requirements in implementations.
+ + + + + +Section: 17.4.3.2 [reserved.names] Status: WP + Submitter: Martin Sebor Date: 2003-09-18
+View all other issues in [reserved.names].
+View all issues with WP status.
+Discussion:
++It has been suggested that 17.4.3.1, p1 may or may not allow programs to +explicitly specialize members of standard templates on user-defined types. +The answer to the question might have an impact where library requirements +are given using the "as if" rule. I.e., if programs are allowed to specialize +member functions they will be able to detect an implementation's strict +conformance to Effects clauses that describe the behavior of the function +in terms of the other member function (the one explicitly specialized by +the program) by relying on the "as if" rule. +
+ + +Proposed resolution:
+ ++ Add the following sentence to 17.4.3.2 [reserved.names], p1: +
+ ++ ++It is undefined for a C++ program to add declarations or definitions to +namespace std or namespaces within namespace std unless otherwise specified. A +program may add template specializations for any standard library template to +namespace std. Such a specialization (complete or partial) of a standard library +template results in undefined behavior unless the declaration depends on a +user-defined type of external linkage and unless the specialization meets the +standard library requirements for the original template.168) +A program has undefined behavior if it declares +
++
+- an explicit specialization of any member function of a standard + library class template, or
+- an explicit specialization of any member function template of a + standard library class or class template, or
+- an explicit or partial specialization of any member class + template of a standard library class or class template.
++A program may explicitly instantiate any templates in the standard library only +if the declaration depends on the name of a user-defined type of external +linkage and the instantiation meets the standard library requirements for the +original template. +
[Kona: straw poll was 6-1 that user programs should not be + allowed to specialize individual member functions of standard + library class templates, and that doing so invokes undefined + behavior. Post-Kona: Martin provided wording.]
+ + +[Sydney: The LWG agrees that the standard shouldn't permit users +to specialize individual member functions unless they specialize the +whole class, but we're not sure these words say what we want them to; +they could be read as prohibiting the specialization of any standard +library class templates. We need to consult with CWG to make sure we +use the right wording.]
+ + + + + + +Section: 20.7.8 [temporary.buffer] Status: WP + Submitter: Martin Sebor Date: 2003-09-18
+View all issues with WP status.
+Discussion:
++The standard is not clear about the requirements on the value returned from +a call to get_temporary_buffer(0). In particular, it fails to specify whether +the call should return a distinct pointer each time it is called (like +operator new), or whether the value is unspecified (as if returned by +malloc). The standard also fails to mention what the required behavior +is when the argument is less than 0. +
+ + +Proposed resolution:
+Change 20.5.3 [meta.help] paragraph 2 from "...or a pair of 0 +values if no storage can be obtained" to "...or a pair of 0 values if +no storage can be obtained or if n <= 0."
+[Kona: Matt provided wording]
+ + + + + +Section: 25.1.12 [alg.search], 25.2.6 [alg.fill], 25.2.7 [alg.generate] Status: WP + Submitter: Martin Sebor Date: 2003-09-18
+View all other issues in [alg.search].
+View all issues with WP status.
+Discussion:
++The complexity requirements for these function templates are incorrect +(or don't even make sense) for negative n:
+ +25.1.9, p7 (search_n):
+
+Complexity: At most (last1 - first1) * count applications
+of the corresponding predicate.
25.2.5, p3 (fill_n):
+
+Complexity: Exactly last - first (or n) assignments.
25.2.6, p3 (generate_n):
+
+Complexity: Exactly last - first (or n) assignments.
+In addition, the Requirements or the Effects clauses for the latter two +templates don't say anything about the behavior when n is negative. +
+ + +Proposed resolution:
+Change 25.1.9, p7 to
+ ++ ++Complexity: At most (last1 - first1) * count applications +of the corresponding predicate if count is positive, +or 0 otherwise. +
Change 25.2.5, p2 to
++ ++Effects: Assigns value through all the iterators in the range [first, +last), or [first, first + n) if n is positive, none otherwise. +
Change 25.2.5, p3 to:
++ ++Complexity: Exactly last - first (or n if n is positive, +or 0 otherwise) assignments. +
+Change 25.2.6, p1 +to (notice the correction for the misspelled "through"): +
++ ++Effects: Invokes the function object genand assigns the return +value of gen through all the iterators in the range [first, last), +or [first, first + n) if n is positive, or [first, first) +otherwise. +
Change 25.2.6, p3 to:
++ + ++Complexity: Exactly last - first (or n if n is positive, +or 0 otherwise) assignments. +
Rationale:
+Informally, we want to say that whenever we see a negative number + we treat it the same as if it were zero. We believe the above + changes do that (although they may not be the minimal way of saying + so). The LWG considered and rejected the alternative of saying that + negative numbers are undefined behavior.
+ + + + + +Section: 21.3.6.5 [string::erase] Status: WP + Submitter: Martin Sebor Date: 2003-09-18
+View all other issues in [string::erase].
+View all issues with WP status.
+Discussion:
++23.1.1, p3 along with Table 67 specify as a prerequisite for a.erase(q) +that q must be a valid dereferenceable iterator into the sequence a. +
+ ++However, 21.3.5.5, p5 describing string::erase(p) only requires that +p be a valid iterator. +
+ ++This may be interepreted as a relaxation of the general requirement, +which is most likely not the intent. +
+ + +Proposed resolution:
+Remove 21.3.6.5 [string::erase] paragraph 5.
+ + +Rationale:
+The LWG considered two options: changing the string requirements to + match the general container requirements, or just removing the + erroneous string requirements altogether. The LWG chose the latter + option, on the grounds that duplicating text always risks the + possibility that it might be duplicated incorrectly.
+ + + + + +Section: 27.7.1.4 [stringbuf.virtuals] Status: WP + Submitter: Christian W Brock Date: 2003-09-24
+View all other issues in [stringbuf.virtuals].
+View all issues with WP status.
+Discussion:
+27.7.1.3 par 8 says:
++ ++Notes: The function can make a write position available only if + ( mode & ios_base::out) != 0. To make a write position + available, the function reallocates (or initially allocates) an + array object with a sufficient number of elements to hold the + current array object (if any), plus one additional write position. + If ( mode & ios_base::in) != 0, the function alters the read end + pointer egptr() to point just past the new write position (as + does the write end pointer epptr()). +
+The sentences "plus one additional write position." and especially + "(as does the write end pointer epptr())" COULD by interpreted + (and is interpreted by at least my library vendor) as: +
+ ++ ++ post-condition: epptr() == pptr()+1 +
+This WOULD force sputc() to call the virtual overflow() each time. +
+ +The proposed change also affects Defect Report 169.
+ + + +Proposed resolution:
+27.7.1.1/2 Change:
+ ++ ++2- Notes: The function allocates no array object. +
+to: +
+ ++ ++2- Postcondition: str() == "". +
+27.7.1.1/3 Change: +
+ +++ ++-3- Effects: Constructs an object of class basic_stringbuf, +initializing the base class with basic_streambuf() +(lib.streambuf.cons), and initializing mode with which . Then copies +the content of str into the basic_stringbuf underlying character +sequence and initializes the input and output sequences according to +which. If which & ios_base::out is true, initializes the output +sequence with the underlying sequence. If which & ios_base::in is +true, initializes the input sequence with the underlying sequence. +
+
to:
+ +++ ++-3- Effects: Constructs an object of class basic_stringbuf, +initializing the base class with basic_streambuf() +(lib.streambuf.cons), and initializing mode with which. Then copies +the content of str into the basic_stringbuf underlying character +sequence. If which & ios_base::out is true, initializes the output +sequence such that pbase() points to the first underlying character, +epptr() points one past the last underlying character, and if (which & +ios_base::ate) is true, pptr() is set equal to +epptr() else pptr() is set equal to pbase(). If which & ios_base::in +is true, initializes the input sequence such that eback() and gptr() +point to the first underlying character and egptr() points one past +the last underlying character. +
+
27.7.1.2/1 Change:
+ +++ ++-1- Returns: A basic_string object whose content is equal to the +basic_stringbuf underlying character sequence. If the buffer is only +created in input mode, the underlying character sequence is equal to +the input sequence; otherwise, it is equal to the output sequence. In +case of an empty underlying character sequence, the function returns +basic_string<charT,traits,Allocator>(). +
+
to:
+ +++ ++-1- Returns: A basic_string object whose content is equal to the +basic_stringbuf underlying character sequence. If the basic_stringbuf +was created only in input mode, the resultant basic_string contains +the character sequence in the range [eback(), egptr()). If the +basic_stringbuf was created with (which & ios_base::out) being true +then the resultant basic_string contains the character sequence in the +range [pbase(), high_mark) where high_mark represents the position one +past the highest initialized character in the buffer. Characters can +be initialized either through writing to the stream, or by +constructing the basic_stringbuf with a basic_string, or by calling +the str(basic_string) member function. In the case of calling the +str(basic_string) member function, all characters initialized prior to +the call are now considered uninitialized (except for those +characters re-initialized by the new basic_string). Otherwise the +basic_stringbuf has been created in neither input nor output mode and +a zero length basic_string is returned. +
+
+27.7.1.2/2 Change: +
+ +++ ++-2- Effects: If the basic_stringbuf's underlying character sequence is +not empty, deallocates it. Then copies the content of s into the +basic_stringbuf underlying character sequence and initializes the +input and output sequences according to the mode stored when creating +the basic_stringbuf object. If (mode&ios_base::out) is true, then +initializes the output sequence with the underlying sequence. If +(mode&ios_base::in) is true, then initializes the input sequence with +the underlying sequence. +
+
to:
+ +++ ++-2- Effects: Copies the content of s into the basic_stringbuf +underlying character sequence. If mode & ios_base::out is true, +initializes the output sequence such that pbase() points to the first +underlying character, epptr() points one past the last underlying +character, and if (mode & ios_base::ate) is true, +pptr() is set equal to epptr() else pptr() is set equal to pbase(). If +mode & ios_base::in is true, initializes the input sequence such that +eback() and gptr() point to the first underlying character and egptr() +points one past the last underlying character. +
+
Remove 27.2.1.2/3. (Same rationale as issue 238: incorrect and unnecessary.)
+ +27.7.1.3/1 Change:
+ +++ ++1- Returns: If the input sequence has a read position available, +returns traits::to_int_type(*gptr()). Otherwise, returns +traits::eof(). +
+
to:
+ +++ ++1- Returns: If the input sequence has a read position available, +returns traits::to_int_type(*gptr()). Otherwise, returns +traits::eof(). Any character in the underlying buffer which has been +initialized is considered to be part of the input sequence. +
+
27.7.1.3/9 Change:
+ +++ ++-9- Notes: The function can make a write position available only if ( +mode & ios_base::out) != 0. To make a write position available, the +function reallocates (or initially allocates) an array object with a +sufficient number of elements to hold the current array object (if +any), plus one additional write position. If ( mode & ios_base::in) != +0, the function alters the read end pointer egptr() to point just past +the new write position (as does the write end pointer epptr()). +
+
to:
+ +++ ++-9- The function can make a write position available only if ( mode & +ios_base::out) != 0. To make a write position available, the function +reallocates (or initially allocates) an array object with a sufficient +number of elements to hold the current array object (if any), plus one +additional write position. If ( mode & ios_base::in) != 0, the +function alters the read end pointer egptr() to point just past the +new write position. +
+
27.7.1.3/12 Change:
+ +++ ++-12- _ If (newoff + off) < 0, or (xend - xbeg) < (newoff + off), the +positioning operation fails. Otherwise, the function assigns xbeg + +newoff + off to the next pointer xnext . +
+
to:
+ +++ ++-12- _ If (newoff + off) < 0, or if (newoff + off) refers to an +uninitialized character (as defined in 27.7.1.3 [stringbuf.members] +paragraph 1), the positioning operation fails. Otherwise, the function +assigns xbeg + newoff + off to the next pointer xnext . +
+
[post-Kona: Howard provided wording. At Kona the LWG agreed that + something along these lines was a good idea, but the original + proposed resolution didn't say enough about the effect of various + member functions on the underlying character sequences.]
+ + + + +Rationale:
+The current basic_stringbuf description is over-constrained in such +a way as to prohibit vendors from making this the high-performance +in-memory stream it was meant to be. The fundamental problem is that +the pointers: eback(), gptr(), egptr(), pbase(), pptr(), epptr() are +observable from a derived client, and the current description +restricts the range [pbase(), epptr()) from being grown geometrically. +This change allows, but does not require, geometric growth of this +range.
+ +Backwards compatibility issues: These changes will break code that +derives from basic_stringbuf, observes epptr(), and depends upon +[pbase(), epptr()) growing by one character on each call to overflow() +(i.e. test suites). Otherwise there are no backwards compatibility +issues.
+ +27.7.1.1/2: The non-normative note is non-binding, and if it were +binding, would be over specification. The recommended change focuses +on the important observable fact.
+ +27.7.1.1/3: This change does two things: 1. It describes exactly +what must happen in terms of the sequences. The terms "input +sequence" and "output sequence" are not well defined. 2. It +introduces a common extension: open with app or ate mode. I concur +with issue 238 that paragraph 4 is both wrong and unnecessary.
+ +27.7.1.2/1: This change is the crux of the efficiency issue. The +resultant basic_string is not dependent upon epptr(), and thus +implementors are free to grow the underlying buffer geometrically +during overflow() *and* place epptr() at the end of that buffer.
+ +27.7.1.2/2: Made consistent with the proposed 27.7.1.1/3.
+ +27.7.1.3/1: Clarifies that characters written to the stream beyond +the initially specified string are available for reading in an i/o +basic_streambuf.
+ +27.7.1.3/9: Made normative by removing "Notes:", and removed the +trailing parenthetical comment concerning epptr().
+ +27.7.1.3/12: Restricting the positioning to [xbeg, xend) is no +longer allowable since [pbase(), epptr()) may now contain +uninitialized characters. Positioning is only allowable over the +initialized range.
+ + + + + +Section: 23.3.5.2 [bitset.members] Status: DR + Submitter: Martin Sebor Date: 2003-10-15
+View all other issues in [bitset.members].
+View all issues with DR status.
+Discussion:
++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. +]
+ + + + + + + + +Section: 21.3.8.9 [string.io] Status: WP + Submitter: Martin Sebor Date: 2003-10-15
+View all other issues in [string.io].
+View all issues with WP status.
+Discussion:
+ +
+It has been pointed out that the proposed resolution in DR 25 may not be
+quite up to snuff:
+http://gcc.gnu.org/ml/libstdc++/2003-09/msg00147.html
+http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#25
+
+It looks like Petur is right. The complete corrected text is copied below. +I think we may have have been confused by the reference to 22.2.2.2.2 and +the subsequent description of `n' which actually talks about the second +argument to sputn(), not about the number of fill characters to pad with. +
+ ++So the question is: was the original text correct? If the intent was to +follow classic iostreams then it most likely wasn't, since setting width() +to less than the length of the string doesn't truncate it on output. This +is also the behavior of most implementations (except for SGI's standard +iostreams where the operator does truncate). +
+ + + +Proposed resolution:
+Change the text in 21.3.7.9, p4 from
+++ If bool(k) is true, inserts characters as if by calling + os.rdbuf()->sputn(str.data(), n), padding as described in stage 3 + of lib.facet.num.put.virtuals, where n is the larger of os.width() + and str.size(); +
to
++ ++ If bool(k) is true, determines padding as described in + lib.facet.num.put.virtuals, and then inserts the resulting + sequence of characters seq as if by calling + os.rdbuf()->sputn(seq, n), where n is the larger of + os.width() and str.size(); +
[Kona: it appears that neither the original wording, DR25, nor the + proposed resolution, is quite what we want. We want to say that + the string will be output, padded to os.width() if necessary. We + don't want to duplicate the padding rules in clause 22, because + they're complicated, but we need to be careful because they weren't + quite written with quite this case in mind. We need to say what + the character sequence is, and then defer to clause 22. Post-Kona: + Benjamin provided wording.]
+ + + + + + + +Section: 22.1.1.1.2 [locale.facet] Status: WP + Submitter: Martin Sebor Date: 2003-10-15
+View all issues with WP status.
+Discussion:
++Is "const std::ctype<char>" a valid template argument to has_facet, use_facet, +and the locale template ctor? And if so, does it designate the same Facet as +the non-const "std::ctype<char>?" What about "volatile std::ctype<char>?" +Different implementations behave differently: some fail to compile, others +accept such types but behave inconsistently. +
+ + +Proposed resolution:
+Change 22.1.1.1.2, p1 to read:
+ +Template parameters in this clause which are required to be facets +are those named Facet in declarations. A program that passes a type +that is not a facet, or a type that refers to volatile-qualified +facet, as an (explicit or deduced) template parameter to a locale +function expecting a facet, is ill-formed. A const-qualified facet is +a valid template argument to any locale function that expects a Facet +template parameter.
+ +[Kona: changed the last sentence from a footnote to normative +text.]
+ + + + + + +Section: 23.1.3 [sequence.reqmts] Status: DR + Submitter: Howard Hinnant Date: 2003-10-20
+View all other issues in [sequence.reqmts].
+View all issues with DR status.
+Discussion:
+ +Section 23.1.3 [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: +
+ +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.3 [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. +
+ + + + + +Section: 27.4.3 [fpos] Status: WP + Submitter: Vincent Leloup Date: 2003-11-17
+View all other issues in [fpos].
+View all issues with WP status.
+Discussion:
++In section 27.4.3.1 [fpos.members] fpos<stateT>::state() is declared +non const, but in section 27.4.3 [fpos] it is declared const. +
+ + +Proposed resolution:
++In section 27.4.3.1 [fpos.members], change the declaration of +fpos<stateT>::state() to const. +
+ + + + + +Section: 27.6.2.4 [ostream::sentry] Status: WP + Submitter: Vincent Leloup Date: 2003-11-18
+View other active issues in [ostream::sentry].
+View all other issues in [ostream::sentry].
+View all issues with WP status.
+Discussion:
++In section 27.6.2.4 [ostream::sentry] paragraph 4, in description part +basic_ostream<charT, traits>::sentry::operator bool() is declared +as non const, but in section 27.6.2.3, in synopsis it is declared +const. +
+ + +Proposed resolution:
++In section 27.6.2.4 [ostream::sentry] paragraph 4, change the declaration +of sentry::operator bool() to const. +
+ + + + + +Section: 27.8.1.4 [filebuf.members] Status: WP + Submitter: Vincent Leloup Date: 2003-11-20
+View all other issues in [filebuf.members].
+View all issues with WP status.
+Discussion:
++In section 27.8.1.4 [filebuf.members] par6, in effects description of +basic_filebuf<charT, traits>::close(), overflow(EOF) is used twice; +should be overflow(traits::eof()). +
+ + +Proposed resolution:
++Change overflow(EOF) to overflow(traits::eof()). +
+ + + + + +Section: 27.8.1 [fstreams] Status: DR + Submitter: Vincent Leloup Date: 2003-11-20
+View all other issues in [fstreams].
+View all issues with DR status.
+Discussion:
+27.8.1.9 [ifstream.members] p1, 27.8.1.13 [ofstream.members] p1, +27.8.1.17 [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). +
Section: 24.3.1 [iterator.traits] Status: DR + Submitter: Dave Abrahams Date: 2003-12-09
+View all issues with DR status.
+Discussion:
++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 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 [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 [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 [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. +]
+ + + + + + + + + +Section: 24.1.5 [random.access.iterators] Status: WP + Submitter: Dave Abrahams Date: 2004-01-07
+View all other issues in [random.access.iterators].
+View all issues with WP status.
+Discussion:
++Table 76, the random access iterator requirement table, says that the +return type of a[n] must be "convertible to T". When an iterator's +value_type T is an abstract class, nothing is convertible to T. +Surely this isn't an intended restriction? +
+ + +Proposed resolution:
++Change the return type to "convertible to T const&". +
+ + + + + +Section: 18.1 [support.types] Status: WP + Submitter: Pete Becker Date: 2004-01-15
+View all other issues in [support.types].
+View all issues with WP status.
+Discussion:
+Original text:
++ ++The macro offsetof accepts a restricted set of type arguments in this +International Standard. type shall be a POD structure or a POD union +(clause 9). The result of applying the offsetof macro to a field that +is a static data member or a function member is undefined." +
Revised text:
++ ++"If type is not a POD structure or a POD union the results are undefined." +
+Looks to me like the revised text should have replaced only the second +sentence. It doesn't make sense standing alone. +
+ + + +Proposed resolution:
+Change 18.1, paragraph 5, to:
+ ++ + + + + ++The macro offsetof accepts a restricted set of type arguments in this +International Standard. If type is not a POD structure or a POD union +the results are undefined. The result of applying the offsetof macro +to a field that is a static data member or a function member is +undefined." +
Section: 27.7.1.4 [stringbuf.virtuals] Status: WP + Submitter: Bill Plauger Date: 2004-01-30
+View all other issues in [stringbuf.virtuals].
+View all issues with WP status.
+Discussion:
+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. +
Section: 27.3 [iostream.objects] Status: DR + Submitter: Bill Plauger Date: 2004-01-30
+View all other issues in [iostream.objects].
+View all issues with DR status.
+Discussion:
++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.]
+ + + + + + +Section: 17.4.1.2 [headers] Status: WP + Submitter: Bill Plauger Date: 2004-01-30
+View all other issues in [headers].
+View all issues with WP status.
+Discussion:
+ +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:
++Add to 17.4.1.2 [headers], para. 4: +
+ ++ ++Except as noted in clauses 18 through 27 and Annex D, the contents of each +header cname shall be the same as that of the corresponding header +name.h, as specified in ISO/IEC 9899:1990 Programming Languages C (Clause +7), or ISO/IEC:1990 Programming Languages-C AMENDMENT 1: C Integrity, (Clause +7), as appropriate, as if by inclusion. In the C++ Standard Library, however, +the declarations
and definitions(except for names which are defined +as macros in C) are within namespace scope (3.3.5) of the namespace std. +It is unspecified whether these names are first declared within the global +namespace scope and are then injected into namespace std by explicit +using-declarations (7.3.3 [namespace.udecl]). +
+Change D.5 [depr.c.headers], para. 2-3: +
+ +++ + + + + ++-2- Every C header, each of which has a name of the form name.h, behaves +as if each name placed in the Standard library namespace by the corresponding +cname header is
+alsoplaced within the global +namespace scope.of the namespace std and is followed +by an explicit using-declaration (7.3.3 [namespace.udecl]).+It is unspecified whether these names are first declared or defined within +namespace scope (3.3.5 [basic.scope.namespace]) of the namespace +std and are then injected into the global namespace scope by explicit +using-declarations (7.3.3 [namespace.udecl]). ++-3- [Example: The header <cstdlib> assuredly +provides its declarations and definitions within the namespace std. +It may also provide these names within the global namespace. The +header <stdlib.h>
+makes these available also in+assuredly provides the same declarations and definitions within the +global namespace, much as in the C Standard. It may also provide these +names within the namespace std. -- end example] +
Section: 23.3.5.1 [bitset.cons] Status: DR + Submitter: Dag Henriksson Date: 2004-01-30
+View all other issues in [bitset.cons].
+View all issues with DR status.
+Discussion:
++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 [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: 27.8.1 [fstreams] Status: DR + Submitter: Ben Hutchings Date: 2004-04-01
+View all other issues in [fstreams].
+View all issues with DR status.
+Discussion:
++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.15 [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.17 [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 [locale.time.get.virtuals] Status: WP + Submitter: Bill Plauger Date: 2004-03-23
+View all issues with WP status.
+Discussion:
++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"
+ + +Change
+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 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. ++ +
to
+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 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: +
+ +date_order() format + + no_order "%m/%d/%y" + dmy "%d/%m/%y" + mdy "%m/%d/%y" + ymd "%y/%m/%d" + ydm "%y/%d/%m" ++
+An implementation may also accept additional implementation-defined formats. +
+ +[Redmond: agreed that this is a real problem. The solution is + probably to match C99's parsing rules. Bill provided wording. +]
+ + + + + + + +Section: 23.2.6 [vector], 23.3.1 [map] Status: WP + Submitter: Thorsten Ottosen Date: 2004-05-12
+View all other issues in [vector].
+View all issues with WP status.
+Discussion:
+ +To add slightly more convenience to vector<T> and map<Key,T> we should consider to add
+Rationale:
+ +Proposed resolution:
+In 23.2.6 [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.6 [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. For a non-empty vector, data() == &front().
+Complexity: Constant time.
+Throws: Nothing.
+
In 23.3.1 [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 [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 [headers] Status: WP + Submitter: Steve Clamage Date: 2004-06-03
+View all other issues in [headers].
+View all issues with WP status.
+Discussion:
+C header <iso646.h> defines macros for some operators, such as +not_eq for !=.
+ +Section 17.4.1.2 [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.1.3.1 [char.traits.specializations.char] Status: WP + Submitter: Martin Sebor Date: 2004-06-28
+View all issues with WP status.
+Discussion:
+ ++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 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.]
+ + + + + + +Section: 27.4.4.3 [iostate.flags] Status: WP + Submitter: Martin Sebor Date: 2004-06-28
+View all other issues in [iostate.flags].
+View all issues with WP status.
+Discussion:
+ +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-bool-type() const; ++
and change [lib.iostate.flags], p1 from
+operator void*() const; ++
to
+operator unspecified-bool-type() const; + + -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. + + -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] ++ +
[Redmond: 5-4 straw poll in favor of doing this.]
+ +[Lillehammer: Doug provided revised wording for + "unspecified-bool-type".]
+ + + + + + + + +Section: 23.2.6 [vector] Status: DR + Submitter: Martin Sebor Date: 2004-06-28
+View all other issues in [vector].
+View all issues with DR status.
+Discussion:
+ ++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: 27.6.2.6.4 [ostream.inserters.character] Status: WP + Submitter: Martin Sebor Date: 2004-07-01
+View all other issues in [ostream.inserters.character].
+View all issues with WP status.
+Discussion:
+ ++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.4 [alg.foreach] Status: WP + Submitter: Stephan T. Lavavej, Jaakko Jarvi Date: 2004-07-09
+View all other issues in [alg.foreach].
+View all issues with WP status.
+Discussion:
++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." +
+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. +
+ ++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. +
+ ++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). +
+ ++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.4 [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.
+ + + + + +Section: 24.1.3 [forward.iterators] Status: WP + Submitter: Dave Abrahams Date: 2004-07-11
+View all other issues in [forward.iterators].
+View all issues with WP status.
+Duplicate of: 477
+Discussion:
++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. ++ +
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.
+ +Related issue: 477
+ + +Proposed resolution:
+ +Remove the "r->m" line from the Forward Iterator requirements +table. Change
++ ++ "const X" +
to
+ ++ ++ "X or const X" +
in paragraph 11 of [lib.iterator.requirements].
+ + + + +Rationale:
++This is a defect because it constrains an lvalue to returning a modifiable lvalue. +
+ + + + + +Section: 25.2.11 [alg.rotate] Status: WP + Submitter: Howard Hinnant Date: 2004-11-22
+View all issues with WP status.
+Discussion:
++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. +
+ ++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)); ++ +
+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); ++ +
+and the resulting program becomes significantly more efficient. +
+ ++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. +
+ + + +Proposed resolution:
+In 25 [algorithms] p2, change:
+ ++ +template<class ForwardIterator> +voidForwardIterator rotate(ForwardIterator first, ForwardIterator middle, + ForwardIterator last); +
In 25.2.11 [alg.rotate], change:
+ ++ +template<class ForwardIterator> +voidForwardIterator rotate(ForwardIterator first, ForwardIterator middle, + ForwardIterator last); +
In 25.2.11 [alg.rotate] insert a new paragraph after p1:
+ +++ +Returns: first + (last - middle).
+
[ +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. +]
+ + +[Howard provided wording for mid-meeting-mailing Jun. 2005.]
+ + +[ +Toronto: moved to Ready. +]
+ + + + + + + +Section: 22 [localization] Status: WP + Submitter: Beman Dawes Date: 2005-01-10
+View all other issues in [localization].
+View all issues with WP status.
+Discussion:
+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.
+ +Clause 22 isn't even listed in 17.3.2.1 [lib.type.descriptions], +either, which is the wording that allows requirements on template +parameters to be identified by name.
+ +So one issue is that 17.3.2.1 [lib.type.descriptions] Should be +changed to cover clause 22. A better change, which will cover us in +the future, would be to say that it applies to all the library +clauses. Then if a template gets added to any library clause we are +covered.
+ +charT, InputIterator, and other names with requirements defined +elsewhere are fine, assuming the 17.3.2.1 [lib.type.descriptions] fix. +But there are a few template arguments names which I don't think have +requirements given elsewhere:
+ +Proposed resolution:
+Change 17.3.2.1 [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 [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.
+ + + + + +Section: 23.2.6 [vector] Status: WP + Submitter: richard@ex-parrot.com Date: 2005-02-10
+View all other issues in [vector].
+View all issues with WP status.
+Discussion:
++In the synopsis of the std::vector<bool> specialisation in 23.2.6 [vector], +the non-template assign() function has the signature
+ +void assign( size_type n, const T& t ); ++ +
The type, T, is not defined in this context.
+ + +Proposed resolution:
+Replace "T" with "value_type".
+ + + + + +Section: 18.2.1.2 [numeric.limits.members] Status: WP + Submitter: Martin Sebor Date: 2005-03-02
+View all other issues in [numeric.limits.members].
+View all issues with WP status.
+Discussion:
+ +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.
+ + + + + +Section: 26.4.1 [rand.req], TR1 5.1.1 [tr.rand.req] Status: WP + Submitter: Walter Brown Date: 2005-07-03
+View all other issues in [rand.req].
+View all issues with WP status.
+Discussion:
++Table 17: Random distribution requirements +
++Row 1 requires that each random distribution provide a nested type "input_type"; +this type denotes the type of the values that the distribution consumes. +
++Inspection of all distributions in [tr.rand.dist] reveals that each distribution +provides a second typedef ("result_type") that denotes the type of the values the +distribution produces when called. +
+ + +Proposed resolution:
++It seems to me that this is also a requirement +for all distributions and should therefore be indicated as such via a new second +row to this table 17: +
+X::result_type | T | --- | compile-time |
[ +Berlin: Voted to WP. N1932 adopts the proposed resolution: see Table 5 row 1. +]
+ + + + + + + +Section: 26.4 [rand], TR1 5.1.3 [tr.rand.var] Status: WP + Submitter: Walter Brown Date: 2005-07-03
+View all other issues in [rand].
+View all issues with WP status.
+Discussion:
++Paragraph 11 of [tr.rand.var] equires that the member template +
++template<class T> result_type operator() (T value); +
+return +
++distribution()(e, value) +
+However, not all distributions have an operator() with a corresponding signature. +
+ +[ +Berlin: As a working group we voted in favor of N1932 which makes this moot: +variate_generator has been eliminated. Then in full committee we voted to give +this issue WP status (mistakenly). +]
+ + + + +Proposed resolution:
++We therefore recommend that we insert the following precondition before paragraph 11: +
++ + + + + ++Precondition: distribution().operator()(e,value) is well-formed. +
Section: 26.4.5 [rand.predef], TR1 5.1.5 [tr.rand.predef] Status: WP + Submitter: Walter Brown Date: 2005-07-03
+View all other issues in [rand.predef].
+View all issues with WP status.
+Discussion:
++The fifth of these engines with predefined parameters, ranlux64_base_01, +appears to have an unintentional error for which there is a simple correction. +The two pre-defined subtract_with_carry_01 engines are given as: +
++typedef subtract_with_carry_01<float, 24, 10, 24> ranlux_base_01; +typedef subtract_with_carry_01<double, 48, 10, 24> ranlux64_base_01; +
+We demonstrate below that ranlux64_base_01 fails to meet the intent of the +random number generation proposal, but that the simple correction to +
++typedef subtract_with_carry_01<double, 48, 5, 12> ranlux64_base_01; +
+does meet the intent of defining well-known good parameterizations. +
++The ranlux64_base_01 engine as presented fails to meet the intent for +predefined engines, stated in proposal N1398 (section E): +
+++In order to make good random numbers available to a large number of library +users, this proposal not only defines generic random-number engines, but also +provides a number of predefined well-known good parameterizations for those. +
+The predefined ranlux_base_01 engine has been proven [1,2,3] to have a very +long period and so meets this criterion. This property makes it suitable for +use in the excellent discard_block engines defined subsequently. The proof +of long period relies on the fact (proven in [1]) that 2**(w*r) - 2**(w*s) ++ 1 is prime (w, r, and s are template parameters to subtract_with_carry_01, +as defined in [tr.rand.eng.sub1]). +
++The ranlux64_base_01 engine as presented in [tr.rand.predef] uses w=48, r=24, s=10. +For these numbers, the combination 2**(w*r)-2**(w*s)+1 is non-prime (though +explicit factorization would be a challenge). In consequence, while it is +certainly possible for some seeding states that this engine would have a very +long period, it is not at all "well-known" that this is the case. The intent +in the N1398 proposal involved the base of the ranlux64 engine, which finds heavy +use in the physics community. This is isomorphic to the predefined ranlux_base_01, +but exploits the ability of double variables to hold (at least) 48 bits of mantissa, +to deliver 48 random bits at a time rather than 24. +
+ + +Proposed resolution:
++To achieve this intended behavior, the correct template parameteriztion would be: +
++typedef subtract_with_carry_01<double, 48, 5, 12> ranlux64_base_01; +
+The sequence of mantissa bits delivered by this is isomorphic (treating each +double as having the bits of two floats) to that delivered by ranlux_base_01. +
++References: +
+[ +Berlin: Voted to WP. N1932 adopts the proposed resolution in 26.3.5, +just above paragraph 5. +]
+ + + + + + + +Section: 23.1.5 [unord.req], TR1 6.3.1 [tr.unord.req] Status: WP + Submitter: Matt Austern Date: 2005-07-03
+View other active issues in [unord.req].
+View all other issues in [unord.req].
+View all issues with WP status.
+Discussion:
++Issue 371 deals with stability of multiset/multimap under insert and erase +(i.e. do they preserve the relative order in ranges of equal elements). +The same issue applies to unordered_multiset and unordered_multimap. +
+[ +Moved to open (from review): There is no resolution. +]
+ + +[ +Toronto: We have a resolution now. Moved to Review. Some concern was noted +as to whether this conflicted with existing practice or not. An additional +concern was in specifying (partial) ordering for an unordered container. +]
+ + + + +Proposed resolution:
++Wording for the proposed resolution is taken from the equivalent text for associative containers. +
+ ++Change 23.1.5 [unord.req], Unordered associative containers, paragraph 6 to: +
+ ++ ++An unordered associative container supports unique keys if it may +contain at most one element for each key. Otherwise, it supports equivalent +keys. unordered_set and unordered_map support +unique keys. unordered_multiset and unordered_multimap +support equivalent keys. In containers that support equivalent keys, elements +with equivalent keys are adjacent to each other. For +unordered_multiset +and unordered_multimap, insert and erase +preserve the relative ordering of equivalent elements. +
+Change 23.1.5 [unord.req], Unordered associative containers, paragraph 8 to: +
+ +++ + + + + + +The elements of an unordered associative container are organized into +buckets. Keys with the same hash code appear in the same bucket. The number +of buckets is automatically increased as elements are added to an unordered +associative container, so that the average number of elements per bucket is kept +below a bound. Rehashing invalidates iterators, changes ordering between +elements, and changes which buckets elements appear in, but does not invalidate +pointers or references to elements. For unordered_multiset +and unordered_multimap, rehashing +preserves the relative ordering of equivalent elements.
+
Section: 23.2.1 [array], TR1 6.2.2 [tr.array.array] Status: WP + Submitter: Pete Becker Date: 2005-07-03
+View other active issues in [array].
+View all other issues in [array].
+View all issues with WP status.
+Discussion:
++array<>::data() is present in the class synopsis, but not documented. +
+ + +Proposed resolution:
++Add a new section, after 6.2.2.3: +
++T* data() +const T* data() const; +
+Returns: elems. +
++Change 6.2.2.4/2 to: +
++ + + + + ++In the case where N == 0, begin() == end(). The return value +of data() is unspecified. +
Section: 20.6.11.1 [func.bind], TR1 3.6 [tr.func.bind] Status: WP + Submitter: Pete Becker Date: 2005-07-03
+View all issues with WP status.
+Discussion:
++In the original proposal for binders, the return type of bind() when +called with a pointer to member data as it's callable object was +defined to be mem_fn(ptr); when Peter Dimov and I unified the +descriptions of the TR1 function objects we hoisted the descriptions +of return types into the INVOKE pseudo-function and into result_of. +Unfortunately, we left pointer to member data out of result_of, so +bind doesn't have any specified behavior when called with a pointer +to member data. +
+ + +Proposed resolution:
+[ +Pete and Peter will provide wording. +]
+ + ++In 20.5.4 [lib.func.ret] ([tr.func.ret]) p3 add the following bullet after bullet 2: +
+[ +Peter provided wording. +]
+ + + + + + + +Section: 20.6.5 [refwrap], TR1 2.1.2 [tr.util.refwrp.refwrp] Status: WP + Submitter: Pete Becker Date: 2005-07-03
+View all issues with WP status.
+Discussion:
++2.1.2/3, second bullet item currently says that reference_wrapper<T> is +derived from unary_function<T, R> if T is: +
+++a pointer to member function type with cv-qualifier cv and no arguments; +the type T1 is cv T* and R is the return type of the pointer to member function; +
+The type of T1 can't be cv T*, 'cause that's a pointer to a pointer to member +function. It should be a pointer to the class that T is a pointer to member of. +Like this: +
+++a pointer to a member function R T0::f() cv (where cv represents the member +function's cv-qualifiers); the type T1 is cv T0* +
+Similarly, bullet item 2 in 2.1.2/4 should be: +
++ + ++a pointer to a member function R T0::f(T2) cv (where cv represents the member +function's cv-qualifiers); the type T1 is cv T0* +
Proposed resolution:
+ ++Change bullet item 2 in 2.1.2/3: +
+ +++ ++
+- +a pointer to member function
+type with cv-qualifier cv and no arguments; +the type T1 is cv T* and R is the return +type of the pointer to member functionR T0::f() cv +(where cv represents the member function's cv-qualifiers); +the type T1 is cv T0* +
+Change bullet item 2 in 2.1.2/4: +
+ +++ + + + + + ++
+- +a pointer to member function
+with cv-qualifier cv and taking one argument +of type T2; the type T1 is cv T* and +R is the return type of the pointer to member function+R T0::f(T2) cv (where cv represents the member +function's cv-qualifiers); the type T1 is cv T0* +
Section: 28 [re] Status: WP + Submitter: Eric Niebler Date: 2005-07-01
+View all other issues in [re].
+View all issues with WP status.
+Discussion:
++This defect is also being discussed on the Boost developers list. The +full discussion can be found here: +http://lists.boost.org/boost/2005/07/29546.php +
++-- Begin original message -- +
++Also, I may have found another issue, closely related to the one under +discussion. It regards case-insensitive matching of named character +classes. The regex_traits<> provides two functions for working with +named char classes: lookup_classname and isctype. To match a char class +such as [[:alpha:]], you pass "alpha" to lookup_classname and get a +bitmask. Later, you pass a char and the bitmask to isctype and get a +bool yes/no answer. +
++But how does case-insensitivity work in this scenario? Suppose we're +doing a case-insensitive match on [[:lower:]]. It should behave as if it +were [[:lower:][:upper:]], right? But there doesn't seem to be enough +smarts in the regex_traits interface to do this. +
++Imagine I write a traits class which recognizes [[:fubar:]], and the +"fubar" char class happens to be case-sensitive. How is the regex engine +to know that? And how should it do a case-insensitive match of a +character against the [[:fubar:]] char class? John, can you confirm this +is a legitimate problem? +
++I see two options: +
++1) Add a bool icase parameter to lookup_classname. Then, +lookup_classname( "upper", true ) will know to return lower|upper +instead of just upper. +
++2) Add a isctype_nocase function +
++I prefer (1) because the extra computation happens at the time the +pattern is compiled rather than when it is executed. +
++-- End original message -- +
+ ++For what it's worth, John has also expressed his preference for option +(1) above. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2409. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2409 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 20.6.11.1.3 [func.bind.bind], TR1 3.6.3 [tr.func.bind.bind] Status: WP + Submitter: Peter Dimov Date: 2005-10-01
+View other active issues in [func.bind.bind].
+View all other issues in [func.bind.bind].
+View all issues with WP status.
+Discussion:
++The original bind proposal gives the guarantee that tr1::bind(f, t1, +..., tN) does not throw when the copy constructors of f, t1, ..., tN +don't. +
+ ++This guarantee is not present in the final version of TR1. +
+ ++I'm pretty certain that we never removed it on purpose. Editorial omission? :-) +
+ +[ +Berlin: not quite editorial, needs proposed wording. +]
+ +[ +Batavia: Doug to translate wording to variadic templates. +]
+ + +[ +Toronto: We agree but aren't quite happy with the wording. The "t"'s no +longer refer to anything. Alan to provide improved wording. +]
+ + + +[ +Pre-Bellevue: Alisdair provided wording. +]
+ + ++TR1 proposed resolution: +
+ +++ + + ++In TR1 3.6.3 [tr.func.bind.bind], add a new paragraph after p2: +
++ ++Throws: Nothing unless one of the copy constructors of f, t1, t2, ..., tN +throws an exception. +
+Add a new paragraph after p4: +
++ ++Throws: nothing unless one of the copy constructors of f, t1, t2, ..., tN +throws an exception. +
Proposed resolution:
++In 20.6.11.1.3 [func.bind.bind], add a new paragraph after p2: +
+ ++Throws: Nothing unless the copy constructor of F or of one of the types +in the BoundArgs... pack expansion throws an exception. ++ +
+In 20.6.11.1.3 [func.bind.bind], add a new paragraph after p4: +
+ ++Throws: Nothing unless the copy constructor of F or of one of the types +in the BoundArgs... pack expansion throws an exception. ++ + + + + + +
Section: 21.3 [basic.string] Status: WP + Submitter: Matt Austern Date: 2005-11-15
+View other active issues in [basic.string].
+View all other issues in [basic.string].
+View all issues with WP status.
+Discussion:
+Issue 69, which was incorporated into C++03, mandated + that the elements of a vector must be stored in contiguous memory. + Should the same also apply to basic_string?
+ +We almost require contiguity already. Clause 23.3.4 [multiset] + defines operator[] as data()[pos]. What's missing + is a similar guarantee if we access the string's elements via the + iterator interface.
+ +Given the existence of data(), and the definition of + operator[] and at in terms of data, + I don't believe it's possible to write a useful and standard- + conforming basic_string that isn't contiguous. I'm not + aware of any non-contiguous implementation. We should just require + it. +
+ + +Proposed resolution:
+Add the following text to the end of 21.3 [basic.string], +paragraph 2.
+ +++ + +The characters in a string are stored contiguously, meaning that if + s is a basic_string<charT, Allocator>, then + it obeys the identity + &*(s.begin() + n) == &*s.begin() + n + for all 0 <= n < s.size(). +
+
Rationale:
++Not standardizing this existing practice does not give implementors more +freedom. We thought it might a decade ago. But the vendors have spoken +both with their implementations, and with their voice at the LWG +meetings. The implementations are going to be contiguous no matter what +the standard says. So the standard might as well give string clients +more design choices. +
+ + + + + +Section: 27.6.1.3 [istream.unformatted] Status: WP + Submitter: Martin Sebor Date: 2005-11-23
+View all other issues in [istream.unformatted].
+View all issues with WP status.
+Discussion:
++The array forms of unformatted input functions don't seem to have well-defined +semantics for zero-element arrays in a couple of cases. The affected ones +(istream::get() and istream::getline()) are supposed to +terminate when (n - 1) characters are stored, which obviously can +never be true when (n == 0) holds to start with. See +c++std-lib-16071. +
+ + +Proposed resolution:
++I suggest changing 27.6.1.3, p7 (istream::get()), bullet 1 to read: +
++Change 27.6.1.3, p9: +
+ ++ ++If the function stores no characters, it calls setstate(failbit) (which +may throw ios_base::failure (27.4.4.3)). In any case, if (n +> 0) is true it then stores a null character into the next +successive location of the array. +
+ +and similarly p17 (istream::getline()), bullet 3 to: + +
++ +In addition, to clarify that istream::getline() must not store the +terminating NUL character unless the the array has non-zero size, Robert +Klarer suggests in c++std-lib-16082 to change 27.6.1.3, p20 to read: + +
++ ++ +In any case, provided (n > 0) is true, it then stores a null character +(using charT()) into the next successive location of the array. + +
[ +post-Redmond: Pete noticed that the current resolution for get requires +writing to out of bounds memory when n == 0. Martin provided fix. +]
+ + + + + + + +Section: 20.7.12.2.11 [util.smartptr.getdeleter], TR1 2.2.3.10 [tr.util.smartptr.getdeleter] Status: DR + Submitter: Paolo Carlini Date: 2005-11-09
+View all other issues in [util.smartptr.getdeleter].
+View all issues with DR status.
+Discussion:
++I'm seeing something that looks like a typo. The Return of get_deleter +says: +
+++If *this owns a deleter d... +
+but get_deleter is a free function! +
+ + +Proposed resolution:
++Therefore, I think should be: +
++ + + + + ++If
*thisp owns a deleter d... +
Section: 21.3 [basic.string] Status: WP + Submitter: Alisdair Meredith Date: 2005-11-16
+View other active issues in [basic.string].
+View all other issues in [basic.string].
+View all issues with WP status.
+Discussion:
++OK, we all know std::basic_string is bloated and already has way too +many members. However, I propose it is missing 3 useful members that +are often expected by users believing it is a close approximation of the +container concept. All 3 are listed in table 71 as 'optional' +
+ ++i/ pop_back. +
+ ++This is the one I feel most strongly about, as I only just discovered it +was missing as we are switching to a more conforming standard library +<g> +
+ ++I find it particularly inconsistent to support push_back, but not +pop_back. +
+ ++ii/ back. +
+ ++There are certainly cases where I want to examine the last character of +a string before deciding to append, or to trim trailing path separators +from directory names etc. *rbegin() somehow feels inelegant. +
+ ++iii/ front +
+ ++This one I don't feel strongly about, but if I can get the first two, +this one feels that it should be added as a 'me too' for consistency. +
+ ++I believe this would be similarly useful to the data() member recently +added to vector, or at() member added to the maps. +
+ + +Proposed resolution:
++Add the following members to definition of class template basic_string, 21.3p7 +
++void pop_back () + +const charT & front() const +charT & front() + +const charT & back() const +charT & back() +
+Add the following paragraphs to basic_string description +
+ ++21.3.4p5 +
+++ +const charT & front() const +charT & front() +++Precondition: !empty() +
++Effects: Equivalent to operator[](0). +
+
+21.3.4p6 +
+++ +const charT & back() const +charT & back() +++Precondition: !empty() +
++Effects: Equivalent to operator[]( size() - 1). +
+
+21.3.5.5p10 +
+++ +void pop_back () +++Precondition: !empty() +
++Effects: Equivalent to erase( size() - 1, 1 ). +
+
+Update Table 71: (optional sequence operations) +Add basic_string to the list of containers for the following operations. +
++ +a.front() +a.back() +a.push_back() +a.pop_back() +a[n] +
[ +Berlin: Has support. Alisdair provided wording. +]
+ + + + + + +Section: 21.3.6.8 [string::swap] Status: WP + Submitter: Beman Dawes Date: 2005-12-14
+View all other issues in [string::swap].
+View all issues with WP status.
+Discussion:
++std::string::swap currently says for effects and postcondition: +
+ +++ ++Effects: Swaps the contents of the two strings. +
+ ++Postcondition: *this contains the characters that were in s, +s contains the characters that were in *this. +
+
+Specifying both Effects and Postcondition seems redundant, and the postcondition +needs to be made stronger. Users would be unhappy if the characters were not in +the same order after the swap. +
+ + +Proposed resolution:
+++ + + + + ++
+ +Effects: Swaps the contents of the two strings.++Postcondition: *this contains the same sequence of +characters that
+werewas in s, +s contains the same sequence of characters that +werewas in *this. +
Section: 27.6.1.3 [istream.unformatted] Status: WP + Submitter: Paolo Carlini Date: 2006-02-12
+View all other issues in [istream.unformatted].
+View all issues with WP status.
+Discussion:
++In the most recent working draft, I'm still seeing: +
+ ++ +seekg(off_type& off, ios_base::seekdir dir) +
+and +
+ ++ +seekp(pos_type& pos) + +seekp(off_type& off, ios_base::seekdir dir) +
+that is, by reference off and pos arguments. +
+ + +Proposed resolution:
++After 27.6.1.3p42 change: +
+ ++ +basic_istream<charT,traits>& seekg(off_type&off, ios_base::seekdir dir); +
+After 27.6.2.4p1 change: +
+ ++ +basic_ostream<charT,traits>& seekp(pos_type&pos); +
+After 27.6.2.4p3 change: +
+ ++ + + + + +basic_ostream<charT,traits>& seekp(off_type&off, ios_base::seekdir dir); +
Section: 25.2.9 [alg.unique] Status: WP + Submitter: Howard Hinnant Date: 2006-02-09
+View all other issues in [alg.unique].
+View all issues with WP status.
+Discussion:
++I believe I botched the resolution of + +241 "Does unique_copy() require CopyConstructible and Assignable?" which now +has WP status. +
+ ++This talks about unique_copy requirements and currently reads: +
+ ++ ++-5- Requires: The ranges [first, last) and +[result, result+(last-first)) +shall not overlap. The expression *result = *first shall +be valid. If neither InputIterator nor OutputIterator meets the +requirements of forward iterator then the value type of InputIterator +must be CopyConstructible (20.1.3). Otherwise CopyConstructible is not required. +
+The problem (which Paolo discovered) is that when the iterators are at their +most restrictive (InputIterator, OutputIterator), then we want +InputIterator::value_type to be both CopyConstructible and +CopyAssignable (for the most efficient implementation). However this +proposed resolution only makes it clear that it is CopyConstructible, +and that one can assign from *first to *result. +This latter requirement does not necessarily imply that you can: +
+ ++ + +*first = *first; +
Proposed resolution:
++ + + + + ++-5- Requires: The ranges [first, last) and +[result, result+(last-first)) +shall not overlap. The expression *result = *first +shall +be valid. If neither InputIterator nor OutputIterator meets the +requirements of forward iterator then the
value type+value_type of InputIterator +must be CopyConstructible (20.1.3) and Assignable. +Otherwise CopyConstructible is not required. +
Section: 20.7.12.2.5 [util.smartptr.shared.obs], TR1 2.2.3.5 [tr.util.smartptr.shared.obs] Status: WP + Submitter: Martin Sebor Date: 2005-10-15
+View all other issues in [util.smartptr.shared.obs].
+View all issues with WP status.
+Discussion:
++I'm trying to reconcile the note in tr.util.smartptr.shared.obs, p6 +that talks about the operator*() member function of shared_ptr: +
+ ++ ++ Notes: When T is void, attempting to instantiate this member function + renders the program ill-formed. [Note: Instantiating shared_ptr<void> + does not necessarily result in instantiating this member function. + --end note] +
+with the requirement in temp.inst, p1: +
+ ++ ++ The implicit instantiation of a class template specialization causes + the implicit instantiation of the declarations, but not of the + definitions... +
+I assume that what the note is really trying to say is that +"instantiating shared_ptr<void> *must not* result in instantiating +this member function." That is, that this function must not be +declared a member of shared_ptr<void>. Is my interpretation +correct? +
+ + +Proposed resolution:
++Change 2.2.3.5p6 +
+ ++ + + + + + ++-6-
Notes:When T is void,attempting to instantiate +this member function renders the program ill-formed. [Note: +Instantiating shared_ptr<void> does not necessarily result in +instantiating this member function. --end note]it is +unspecified whether this member function is declared or not, and if so, what its +return type is, except that the declaration (although not necessarily the +definition) of the function shall be well-formed. +
Section: 20.7.12.2 [util.smartptr.shared], TR1 2.2.3 [tr.util.smartptr.shared] Status: WP + Submitter: Martin Sebor Date: 2005-10-16
+View other active issues in [util.smartptr.shared].
+View all other issues in [util.smartptr.shared].
+View all issues with WP status.
+Discussion:
++Is the void specialization of the template assignment operator taking +a shared_ptr<void> as an argument supposed be well-formed? +
++I.e., is this snippet well-formed: +
++ +shared_ptr<void> p; +p.operator=<void>(p); +
+Gcc complains about auto_ptr<void>::operator*() returning a reference +to void. I suspect it's because shared_ptr has two template assignment +operators, one of which takes auto_ptr, and the auto_ptr template gets +implicitly instantiated in the process of overload resolution. +
+ ++The only way I see around it is to do the same trick with auto_ptr<void> +operator*() as with the same operator in shared_ptr<void>. +
+ ++PS Strangely enough, the EDG front end doesn't mind the code, even +though in a small test case (below) I can reproduce the error with +it as well. +
+ ++ + +template <class T> +struct A { T& operator*() { return *(T*)0; } }; + +template <class T> +struct B { + void operator= (const B&) { } + template <class U> + void operator= (const B<U>&) { } + template <class U> + void operator= (const A<U>&) { } +}; + +int main () +{ + B<void> b; + b.operator=<void>(b); +} +
Proposed resolution:
++In [lib.memory] change: +
++ +template<class X> class auto_ptr; +template<> class auto_ptr<void>; +
+In [lib.auto.ptr]/2 add the following before the last closing brace: +
+ ++ + + + + + +template<> class auto_ptr<void> +{ +public: + typedef void element_type; +}; +
Section: 20.7.12.2.5 [util.smartptr.shared.obs], TR1 2.2.3.5 [tr.util.smartptr.shared.obs] Status: WP + Submitter: Martin Sebor Date: 2005-10-18
+View all other issues in [util.smartptr.shared.obs].
+View all issues with WP status.
+Discussion:
++Peter Dimov wrote: +To: C++ libraries mailing list +Message c++std-lib-15614 +[...] +The intent is for both use_count() and unique() to work in a threaded environment. +They are intrinsically prone to race conditions, but they never return garbage. +
+ ++This is a crucial piece of information that I really wish were +captured in the text. Having this in a non-normative note would +have made everything crystal clear to me and probably stopped +me from ever starting this discussion :) Instead, the sentence +in p12 "use only for debugging and testing purposes, not for +production code" very strongly suggests that implementations +can and even are encouraged to return garbage (when threads +are involved) for performance reasons. +
++How about adding an informative note along these lines: +
+++ Note: Implementations are encouraged to provide well-defined + behavior for use_count() and unique() even in the presence of + multiple threads. +
+I don't necessarily insist on the exact wording, just that we +capture the intent. +
+ + +Proposed resolution:
++Change 20.7.12.2.5 [util.smartptr.shared.obs] p12: +
++ ++[Note: use_count() is not necessarily efficient.
Use only for +debugging and testing purposes, not for production code.--end note] +
+Change 20.7.12.3.5 [util.smartptr.weak.obs] p3: +
++ + + + + ++[Note: use_count() is not necessarily efficient.
Use only for +debugging and testing purposes, not for production code.--end note] +
Section: 26.5.4 [class.slice] Status: WP + Submitter: Howard Hinnant Date: 2005-11-03
+View all issues with WP status.
+Discussion:
++If one explicitly constructs a slice or glice with the default +constructor, does the standard require this slice to have any usable +state? It says "creates a slice which specifies no elements", which +could be interpreted two ways: +
++Here is a bit of code to illustrate: +
++ +#include <iostream> +#include <valarray> + +int main() +{ + std::valarray<int> v(10); + std::valarray<int> v2 = v[std::slice()]; + std::cout << "v[slice()].size() = " << v2.size() << '\n'; +} +
+Is the behavior undefined? Or should the output be: +
+ ++ +v[slice()].size() = 0 +
+There is a similar question and wording for gslice at 26.3.6.1p1. +
+ + +Proposed resolution:
+ +[Martin suggests removing the second sentence in 26.5.4.1 [cons.slice] as well.]
+ + ++Change 26.5.4.1 [cons.slice]: +
+ ++ ++1 -
The default constructor for slice creates a slice +which specifies no elements.The default constructor is equivalent to +slice(0, 0, 0). A default constructor is provided only to permit +the declaration of arrays of slices. The constructor with arguments for a slice +takes a start, length, and stride parameter. +
+Change 26.5.6.1 [gslice.cons]: +
+ ++ + + + + + ++1 -
The default constructor creates a gslice which specifies no +elements.The default constructor is equivalent to gslice(0, +valarray<size_t>(), valarray<size_t>()). The constructor +with arguments builds a gslice based on a specification of start, +lengths, and strides, as explained in the previous section. +
Section: 20.7.12.2.11 [util.smartptr.getdeleter], TR1 2.2.3.2 [tr.util.smartptr.shared.dest] Status: WP + Submitter: Matt Austern Date: 2006-01-10
+View all other issues in [util.smartptr.getdeleter].
+View all issues with WP status.
+Discussion:
++The description of ~shared_ptr doesn't say when the shared_ptr's deleter, if +any, is destroyed. In principle there are two possibilities: it is destroyed +unconditionally whenever ~shared_ptr is executed (which, from an implementation +standpoint, means that the deleter is copied whenever the shared_ptr is copied), +or it is destroyed immediately after the owned pointer is destroyed (which, from +an implementation standpoint, means that the deleter object is shared between +instances). We should say which it is. +
+ + +Proposed resolution:
++Add after the first sentence of 20.7.12.2.11 [util.smartptr.getdeleter]/1: +
+++ + + + + ++The returned pointer remains valid as long as there exists a shared_ptr instance +that owns d. +
++[Note: it is unspecified whether the pointer remains valid longer than that. +This can happen if the implementation doesn't destroy the deleter until all +weak_ptr instances in the ownership group are destroyed. -- end note] +
+
Section: 26.7 [c.math] Status: WP + Submitter: Howard Hinnant Date: 2006-01-12
+View all other issues in [c.math].
+View all issues with WP status.
+Discussion:
++Assuming we adopt the +C +compatibility package from C99 what should be the return type of the +following signature be: +
++? pow(float, int); +
+C++03 says that the return type should be float. + +TR1 and C90/99 say the return type should be double. This can put +clients into a situation where C++03 provides answers that are not as high +quality as C90/C99/TR1. For example: +
++#include <math.h> + +int main() +{ + float x = 2080703.375F; + double y = pow(x, 2); +} +
+Assuming an IEEE 32 bit float and IEEE 64 bit double, C90/C99/TR1 all suggest: +
+ ++ +y = 4329326534736.390625 +
+which is exactly right. While C++98/C++03 demands: +
+ ++ +y = 4329326510080. +
+which is only approximately right. +
+ ++I recommend that C++0X adopt the mixed mode arithmetic already adopted by +Fortran, C and TR1 and make the return type of pow(float,int) be +double. +
+ +[ +Kona (2007): Other functions that are affected by this issue include +ldexp, scalbln, and scalbn. We also believe that there is a typo in +26.7/10: float nexttoward(float, long double); [sic] should be float +nexttoward(float, float); Proposed Disposition: Review (the proposed +resolution appears above, rather than below, the heading "Proposed +resolution") +]
+ + +[ +
+Howard, post Kona: +
+++] + + ++Unfortunately I strongly disagree with a part of the resolution +from Kona. I am moving from New to Open instead of to Review because I do not believe +we have consensus on the intent of the resolution. +
++This issue does not include ldexp, scalbln, and scalbn because +the second integral parameter in each of these signatures (from C99) is not a +generic parameter according to C99 7.22p2. The corresponding C++ overloads are +intended (as far as I know) to correspond directly to C99's definition of generic parameter. +
++For similar reasons, I do not believe that the second long double parameter of +nexttoward, nor the return type of this function, is in error. I believe the +correct signature is: +
+++float nexttoward(float, long double); +++which is what both the C++0X working paper and C99 state (as far as I currently understand). +
++This is really only about pow(float, int). And this is because C++98 took one +route (with pow only) and C99 took another (with many math functions in <tgmath.h>. +The proposed resolution basically says: C++98 got it wrong and C99 got it right; let's go with C99. +
+
[ +Bellevue: +]
+ + ++This signature was not picked up from C99. Instead, if one types +pow(2.0f,2), the promotion rules will invoke "double pow(double, +double)", which generally gives special treatment for integral +exponents, preserving full accuracy of the result. New proposed +wording provided. ++ + +
Proposed resolution:
++Change 26.7 [c.math] p10: +
+ +++ + + + + + ++The added signatures are: +
++... +float pow(float, int);+... +double pow(double, int);+... +long double pow(long double, int);+
Section: 26.3.11 [cmplxh], TR1 8.3 [tr.c99.cmplxh] Status: WP + Submitter: Howard Hinnant Date: 2006-01-23
+View all issues with WP status.
+Discussion:
++Previously xxx.h was parsable by C++. But in the case of C99's <complex.h> +it isn't. Otherwise we could model it just like <string.h>, <cstring>, <string>: +
+ ++In the case of C's complex, the C API won't compile in C++. So we have: +
+ ++The ? can't refer to the C API. TR1 currently says: +
+ +Proposed resolution:
++Change 26.3.11 [cmplxh]: +
+ +++ + + + + + ++The header behaves as if it includes the header +<ccomplex>.
+, and provides sufficient using +declarations to declare in the global namespace all function and type names +declared or defined in the neader <complex>.+[Note: <complex.h> does not promote any interface +into the global namespace as there is no C interface to promote. --end +note] +
Section: 25.2.12 [alg.random.shuffle] Status: WP + Submitter: Martin Sebor Date: 2006-01-25
+View all issues with WP status.
+Discussion:
++...is specified to shuffle its range by calling swap but not how +(or even that) it's supposed to use the RandomNumberGenerator +argument passed to it. +
++Shouldn't we require that the generator object actually be used +by the algorithm to obtain a series of random numbers and specify +how many times its operator() should be invoked by the algorithm? +
+ ++See N2391 and +N2423 +for some further discussion. +
+ + + +Proposed resolution:
++Adopt the proposed resolution in +N2423. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 18.2.1 [limits] Status: WP + Submitter: Martin Sebor Date: 2006-02-19
+View all other issues in [limits].
+View all issues with WP status.
+Discussion:
+
+
+18.2.1 [limits], p2 requires implementations to provide specializations of the
+numeric_limits
template for each scalar type. While this
+could be interepreted to include cv-qualified forms of such types such
+an interepretation is not reflected in the synopsis of the
+<limits>
header.
+
+
+
+The absence of specializations of the template on cv-qualified forms
+of fundamental types makes numeric_limits
difficult to
+use in generic code where the constness (or volatility) of a type is
+not always immediately apparent. In such contexts, the primary
+template ends up being instantiated instead of the provided
+specialization, typically yielding unexpected behavior.
+
+
+
+Require that specializations of numeric_limits
on
+cv-qualified fundamental types have the same semantics as those on the
+unqualifed forms of the same types.
+
+
Proposed resolution:
+
+
+Add to the synopsis of the <limits>
header,
+immediately below the declaration of the primary template, the
+following:
+
+template <class T> class numeric_limits<const T>; +template <class T> class numeric_limits<volatile T>; +template <class T> class numeric_limits<const volatile T>; + ++ +
+ +Add a new paragraph to the end of 18.2.1.1 [numeric.limits], with the following +text: + +
+
+
+-new-para- The value of each member of a numeric_limits
+specialization on a cv-qualified T is equal to the value of the same
+member of numeric_limits<T>
.
+
+
[ +Portland: Martin will clarify that user-defined types get cv-specializations +automatically. +]
+ + + + + + + +Section: 24.4.2.6.5 [inserter] Status: WP + Submitter: Howard Hinnant Date: 2006-02-21
+View all issues with WP status.
+Discussion:
++The declaration of std::inserter is: +
+ ++ +template <class Container, class Iterator> +insert_iterator<Container> +inserter(Container& x, Iterator i); +
+The template parameter Iterator in this function is completely unrelated +to the template parameter Container when it doesn't need to be. This +causes the code to be overly generic. That is, any type at all can be deduced +as Iterator, whether or not it makes sense. Now the same is true of +Container. However, for every free (unconstrained) template parameter +one has in a signature, the opportunity for a mistaken binding grows geometrically. +
+ ++It would be much better if inserter had the following signature instead: +
+ ++ +template <class Container> +insert_iterator<Container> +inserter(Container& x, typename Container::iterator i); +
+Now there is only one free template parameter. And the second argument to +inserter must be implicitly convertible to the container's iterator, +else the call will not be a viable overload (allowing other functions in the +overload set to take precedence). Furthermore, the first parameter must have a +nested type named iterator, or again the binding to std::inserter +is not viable. Contrast this with the current situation +where any type can bind to Container or Iterator and those +types need not be anything closely related to containers or iterators. +
+ ++This can adversely impact well written code. Consider: +
+ ++ +#include <iterator> +#include <string> + +namespace my +{ + +template <class String> +struct my_type {}; + +struct my_container +{ +template <class String> +void push_back(const my_type<String>&); +}; + +template <class String> +void inserter(const my_type<String>& m, my_container& c) {c.push_back(m);} + +} // my + +int main() +{ + my::my_container c; + my::my_type<std::string> m; + inserter(m, c); +} +
+Today this code fails because the call to inserter binds to +std::inserter instead of to my::inserter. However with the +proposed change std::inserter will no longer be a viable function which +leaves only my::inserter in the overload resolution set. Everything +works as the client intends. +
+ ++To make matters a little more insidious, the above example works today if you +simply change the first argument to an rvalue: +
+ ++ +inserter(my::my_type(), c); +
+It will also work if instantiated with some string type other than +std::string (or any other std type). It will also work if +<iterator> happens to not get included. +
+ ++And it will fail again for such inocuous reaons as my_type or +my_container privately deriving from any std type. +
+ ++It seems unfortunate that such simple changes in the client's code can result +in such radically differing behavior. +
+ + + +Proposed resolution:
++Change 24.2: +
+ ++ ++24.2 Header <iterator> synopsis +
++... +template <class Container, class Iterator> + insert_iterator<Container> inserter(Container& x,Iteratortypename Container::iterator i); +... +
+Change 24.4.2.5: +
+ ++ ++24.4.2.5 Class template insert_iterator
++... +template <class Container, class Iterator> + insert_iterator<Container> inserter(Container& x,Iteratortypename Container::iterator i); +... +
+Change 24.4.2.6.5: +
+ +++ + + ++24.4.2.6.5 inserter +
+template <class Container+, class Inserter> + insert_iterator<Container> inserter(Container& x,Insertertypename Container::iterator i); +++-1- Returns: insert_iterator<Container>(x,
typename Container::iterator(i)). +
[ +Kona (2007): This issue will probably be addressed as a part of the +concepts overhaul of the library anyway, but the proposed resolution is +correct in the absence of concepts. Proposed Disposition: Ready +]
+ + + + + +Section: 27.7 [string.streams] Status: WP + Submitter: Martin Sebor Date: 2006-02-23
+View all other issues in [string.streams].
+View all issues with WP status.
+Discussion:
+
+
+For better efficiency, the requirement on the stringbuf ctor that
+takes a string argument should be loosened up to let it set
+epptr()
beyond just one past the last initialized
+character just like overflow()
has been changed to be
+allowed to do (see issue 432). That way the first call to
+sputc()
on an object won't necessarily cause a call to
+overflow
. The corresponding change should be made to the
+string overload of the str()
member function.
+
+
Proposed resolution:
++ +Change 27.7.1.1, p3 of the Working Draft, N1804, as follows: + +
+ ++ +explicit basic_stringbuf(const basic_string<charT,traits,Allocator>& s+ +tr, + ios_base::openmode which = ios_base::in | ios_base::out); ++-3- Effects: Constructs an object of class basic_stringbuf, +initializing the base class with basic_streambuf() +(27.5.2.1), and initializing mode with which. +Then calls str(s).
+copies the content of +str into the basic_stringbuf underlying character +sequence. If which & ios_base::out is true, initializes the +output sequence such that pbase() points to the first underlying +character, epptr() points one past the last underlying character, and +pptr() is equal to epptr() if which & ios_base::ate +is true, otherwise pptr() is equal to pbase(). If +which & ios_base::in is true, initializes the input sequence such +that eback() and gptr() point to the first underlying +character and egptr() points one past the last underlying character.+
+
+Change the Effects clause of the str()
in 27.7.1.2, p2 to
+read:
+
+
++ + ++-2- Effects: Copies the contents of s into the +basic_stringbuf underlying character sequence and +initializes the input and output sequences according to mode. +
+ +If +mode & ios_base::out is true, initializes the output +sequence such that pbase() points to the first underlying character, +epptr() points one past the last underlying character, and pptr() +is equal to epptr() if mode & ios_base::in +is true, otherwise pptr() is equal to pbase(). If +mode & ios_base::in is true, initializes the input sequence +such that eback() and gptr() point to the first underlying +character and egptr() points one past the last underlying character.++ +-3- Postconditions: If
+mode & ios_base::out
is true, +pbase()
points to the first underlying character and +(epptr() >= pbase() + s.size())
holds; in addition, if +mode & ios_base::in
is true,(pptr() == pbase() ++ s.data())
holds, otherwise(pptr() == pbase())
+is true. Ifmode & ios_base::in
is true, +eback()
points to the first underlying character, and +(gptr() == eback())
and(egptr() == eback() + +s.size())
hold. + +
[ +Kona (2007) Moved to Ready. +]
+ + + + + +Section: 27.7.1.4 [stringbuf.virtuals] Status: WP + Submitter: Martin Sebor Date: 2006-02-23
+View all other issues in [stringbuf.virtuals].
+View all issues with WP status.
+Discussion:
+
+According to Table 92 (unchanged by issue 432), when (way ==
+end)
the newoff
value in out mode is computed as
+the difference between epptr()
and pbase()
.
+
+
+This value isn't meaningful unless the value of epptr()
+can be precisely controlled by a program. That used to be possible
+until we accepted the resolution of issue 432, but since then the
+requirements on overflow()
have been relaxed to allow it
+to make more than 1 write position available (i.e., by setting
+epptr()
to some unspecified value past
+pptr()
). So after the first call to
+overflow()
positioning the output sequence relative to
+end will have unspecified results.
+
+
+
+In addition, in in|out
mode, since (egptr() ==
+epptr())
need not hold, there are two different possible values
+for newoff
: epptr() - pbase()
and
+egptr() - eback()
.
+
+
Proposed resolution:
+
+
+Change the newoff
column in the last row of Table 94 to
+read:
+
+
+ + ++ +the
endhigh mark pointer minus the beginning +pointer (). + +
xendhigh_mark - xbeg
[ +Kona (2007) Moved to Ready. +]
+ + + + + +Section: 27.6.1.3 [istream.unformatted] Status: WP + Submitter: Martin Sebor Date: 2006-02-23
+View all other issues in [istream.unformatted].
+View all issues with WP status.
+Discussion:
++ +The array forms of unformatted input functions don't have well-defined +semantics for zero-element arrays in a couple of cases. The affected +ones (istream::get() and getline()) are supposed to +terminate when (n - 1) characters are stored, which obviously +can never be true when (n == 0) to start with. + +
+ + +Proposed resolution:
++ +I propose the following changes (references are relative to the +Working Draft (document N1804). + +
++ +Change 27.6.1.3, p8 (istream::get()), bullet 1 as follows: + +
++++ +if (n < 1) is true or (n - 1) +characters are stored; + +
+
+ +Similarly, change 27.6.1.3, p18 (istream::getline()), bullet +3 as follows: + +
++++ +(n < 1) is true or (n - 1) characters +are stored (in which case the function calls +setstate(failbit)). + +
+
+ +Finally, change p21 as follows: + +
+++ + + + + ++ +In any case, provided (n > 0) is true, it then +stores a null character (using charT()) into the next successive +location of the array. + +
+
Section: 27.6 [iostream.format] Status: WP + Submitter: Martin Sebor Date: 2006-02-25
+View all other issues in [iostream.format].
+View all issues with WP status.
+Discussion:
++ +Issue 60 explicitly made the extractor and inserter operators that +take a basic_streambuf* argument formatted input and output +functions, respectively. I believe that's wrong, certainly in the +case of the extractor, since formatted functions begin by extracting +and discarding whitespace. The extractor should not discard any +characters. + +
+ + +Proposed resolution:
++ +I propose to change each operator to behave as unformatted input and +output function, respectively. The changes below are relative to the +working draft document number N1804. + +
++ +Specifically, change 27.6.1.2.3, p14 as follows: + +
+ ++++ +Effects: Behaves as an unformatted input function +(as described in
+27.6.1.2.127.6.1.3, paragraph +1). + +
+ +And change 27.6.2.5.3, p7 as follows: + +
+ +++ + ++ +Effects: Behaves as an unformatted output function +(as described in
+27.6.2.5.127.6.2.6, paragraph +1). + +
[ +Kona (2007): Proposed Disposition: Ready +]
+ + + + + +Section: 27.3 [iostream.objects] Status: WP + Submitter: Pete Becker Date: 2006-04-18
+View all other issues in [iostream.objects].
+View all issues with WP status.
+Discussion:
++lib.iostream.objects requires that the standard stream objects are never +destroyed, and it requires that they be destroyed. +
++DR 369 adds words to say that we really mean for ios_base::Init objects to force +construction of standard stream objects. It ends, though, with the phrase "these +stream objects shall be destroyed after the destruction of dynamically ...". +However, the rule for destruction is stated in the standard: "The objects are +not destroyed during program execution." +
+ + +Proposed resolution:
++Change 27.3 [iostream.objects]/1: +
+ +++ + ++-2- The objects are constructed and the associations are established at +some time prior to or during the first time an object of class +ios_base::Init is constructed, and in any case before the body of main +begins execution.290) The objects are not destroyed during program +execution.291) If a translation unit includes <iostream&t; or explicitly +constructs an ios_base::Init object, these stream objects shall be +constructed before dynamic initialization of non-local objects defined +later in that translation unit
+, and these stream objects shall be +destroyed after the destruction of dynamically initialized non-local +objects defined later in that translation unit. +
[ +Kona (2007): From 27.3 [iostream.objects]/2, strike the words "...and these stream objects +shall be destroyed after the destruction of dynamically initialized +non-local objects defined later in that translation unit." Proposed +Disposition: Review +]
+ + + + + +Section: 20.7.12.2.2 [util.smartptr.shared.dest], TR1 2.2.3.2 [tr.util.smartptr.shared.dest] Status: WP + Submitter: Peter Dimov Date: 2006-04-23
+View all issues with WP status.
+Discussion:
++[tr.util.smartptr.shared.dest] says in its second bullet: +
+ ++"If *this shares ownership with another shared_ptr instance (use_count() > 1), +decrements that instance's use count." +
+ ++The problem with this formulation is that it presupposes the existence of an +"use count" variable that can be decremented and that is part of the state of a +shared_ptr instance (because of the "that instance's use count".) +
+ ++This is contrary to the spirit of the rest of the specification that carefully +avoids to require an use count variable. Instead, use_count() is specified to +return a value, a number of instances. +
+ ++In multithreaded code, the usual implicit assumption is that a shared variable +should not be accessed by more than one thread without explicit synchronization, +and by introducing the concept of an "use count" variable, the current wording +implies that two shared_ptr instances that share ownership cannot be destroyed +simultaneously. +
+ ++In addition, if we allow the interpretation that an use count variable is part +of shared_ptr's state, this would lead to other undesirable consequences WRT +multiple threads. For example, +
+ ++ +p1 = p2; +
+would now visibly modify the state of p2, a "write" operation, requiring a lock. +
+ + +Proposed resolution:
++Change the first two bullets of [lib.util.smartptr.shared.dest]/1 to: +
+ +++ ++
+- If *this is empty or shares ownership with another +shared_ptr instance (use_count() > 1), there are no side effects.
+- +
If *this shares ownership with another shared_ptr instance +(use_count() > 1), decrements that instance's use count.
+Add the following paragraph after [lib.util.smartptr.shared.dest]/1: +
+ ++ + + + + ++[Note: since the destruction of *this decreases the number of instances in +*this's ownership group by one, all shared_ptr instances that share ownership +with *this will report an use_count() that is one lower than its previous value +after *this is destroyed. --end note] +
Section: 25.1.7 [alg.find.first.of] Status: WP + Submitter: Doug Gregor Date: 2006-04-25
+View all other issues in [alg.find.first.of].
+View all issues with WP status.
+Discussion:
++In 25.1.4 Find First [lib.alg.find.first], the two iterator type parameters to +find_first_of are specified to require Forward Iterators, as follows: +
+ ++ +template<class ForwardIterator1, class ForwardIterator2> + ForwardIterator1 + find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2); +template<class ForwardIterator1, class ForwardIterator2, + class BinaryPredicate> +ForwardIterator1 + find_first_of(ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred); +
+However, ForwardIterator1 need not actually be a Forward Iterator; an Input +Iterator suffices, because we do not need the multi-pass property of the Forward +Iterator or a true reference. +
+ + +Proposed resolution:
++Change the declarations of find_first_of to: +
+ ++ + + + + + +template<classForwardIterator1InputIterator1, class ForwardIterator2> +ForwardIterator1InputIterator1 + find_first_of(ForwardIterator1InputIterator1 first1,ForwardIterator1InputIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2); +template<classForwardIterator1InputIterator1, class ForwardIterator2, + class BinaryPredicate> +ForwardIterator1InputIterator1 + find_first_of(ForwardIterator1InputIterator1 first1,ForwardIterator1InputIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate pred); +
Section: 25.3.3.2 [upper.bound] Status: WP + Submitter: Seungbeom Kim Date: 2006-05-03
+View all issues with WP status.
+Discussion:
++ISO/IEC 14882:2003 says: +
+ +++ ++25.3.3.2 upper_bound +
++Returns: The furthermost iterator i in the range +[first, last) such that +for any iterator j in the range [first, i) the following corresponding +conditions hold: !(value < *j) or comp(value, *j) == false. +
+
+From the description above, upper_bound cannot return last, since it's +not in the interval [first, last). This seems to be a typo, because if +value is greater than or equal to any other values in the range, or if +the range is empty, returning last seems to be the intended behaviour. +The corresponding interval for lower_bound is also [first, last]. +
+ + +Proposed resolution:
++Change [lib.upper.bound]: +
+ +++ + + + + + ++Returns: The furthermost iterator i in the range +[first, last
+)] such that +for any iterator j in the range [first, i) the following corresponding +conditions hold: !(value < *j) or comp(value, *j) == false. +
Section: 20.7.5.1 [allocator.members] Status: WP + Submitter: Martin Sebor Date: 2006-05-17
+View all other issues in [allocator.members].
+View all issues with WP status.
+Discussion:
+
+
+The description of the allocator member function
+allocate()
requires that the hint argument be
+either 0 or a value previously returned from allocate()
.
+Footnote 227 further suggests that containers may pass the address of
+an adjacent element as this argument.
+
+
+
+I believe that either the footnote is wrong or the normative
+requirement that the argument be a value previously returned from a
+call to allocate()
is wrong. The latter is supported by
+the resolution to issue 20-004 proposed in c++std-lib-3736 by Nathan
+Myers. In addition, the hint is an ordinary void* and not the
+pointer
type returned by allocate()
, with
+the two types potentially being incompatible and the requirement
+impossible to satisfy.
+
+
+ +See also c++std-lib-14323 for some more context on where this came up +(again). + +
+ + +Proposed resolution:
+
+
+Remove the requirement in 20.6.1.1, p4 that the hint be a value
+previously returned from allocate()
. Specifically, change
+the paragraph as follows:
+
+
+Requires: hint either 0 or previously obtained from member
+ [Note: The value hint may be used by an
+implementation to help improve performance. -- end note]
+allocate
and not yet passed to member deallocate
.
+The value hint may be used by an implementation to help improve performance
+223).
+ + + + ++
[Footnote: 223)In a container member function, the address of an +adjacent element is often a good choice to pass for this argument.+
flush()
not unformatted functionSection: 27.6.2.7 [ostream.unformatted] Status: WP + Submitter: Martin Sebor Date: 2006-06-14
+View all other issues in [ostream.unformatted].
+View all issues with WP status.
+Discussion:
+
+
+The resolution of issue 60 changed basic_ostream::flush()
+so as not to require it to behave as an unformatted output function.
+That has at least two in my opinion problematic consequences:
+
+
+
+First, flush()
now calls rdbuf()->pubsync()
+unconditionally, without regard to the state of the stream. I can't
+think of any reason why flush()
should behave differently
+from the vast majority of stream functions in this respect.
+
+
+
+Second, flush()
is not required to catch exceptions from
+pubsync()
or set badbit
in response to such
+events. That doesn't seem right either, as most other stream functions
+do so.
+
+
Proposed resolution:
+
+
+I propose to revert the resolution of issue 60 with respect to
+flush()
. Specifically, I propose to change 27.6.2.6, p7
+as follows:
+
+
+Effects: Behaves as an unformatted output function (as described
+in 27.6.2.6, paragraph 1). If rdbuf()
is not a null
+pointer, constructs a sentry object. If this object returns
+true
when converted to a value of type bool the function
+calls rdbuf()->pubsync()
. If that function returns
+-1 calls setstate(badbit)
(which may throw
+ios_base::failure
(27.4.4.3)). Otherwise, if the
+sentry object returns false
, does nothing.Does
+not behave as an unformatted output function (as described in
+27.6.2.6, paragraph 1).
+
[ +Kona (2007): Proposed Disposition: Ready +]
+ + + + + +Section: 21.3.8.9 [string.io] Status: WP + Submitter: Martin Sebor Date: 2006-06-22
+View all other issues in [string.io].
+View all issues with WP status.
+Discussion:
++ +Section and paragraph numbers in this paper are relative to the +working draft document number N2009 from 4/21/2006. + +
+ +
+
+The basic_string
extractor in 21.3.7.9, p1 is clearly
+required to behave as a formatted input function, as is the
+std::getline()
overload for string described in p7.
+
+
+
+However, the basic_string
inserter described in p5 of the
+same section has no such requirement. This has implications on how the
+operator responds to exceptions thrown from xsputn()
+(formatted output functions are required to set badbit
+and swallow the exception unless badbit
is also set in
+exceptions()
; the string inserter doesn't have any such
+requirement).
+
+
+ +I don't see anything in the spec for the string inserter that would +justify requiring it to treat exceptions differently from all other +similar operators. (If it did, I think it should be made this explicit +by saying that the operator "does not behave as a formatted output +function" as has been made customary by the adoption of the resolution +of issue 60). + +
+ + +Proposed resolution:
++ +I propose to change the Effects clause in 21.3.7.9, p5, as follows: + +
++++ +Effects:
+Begins by constructing a sentry object k as if k +were constructed by typenameBehaves as a formatted output function +(27.6.2.5.1). After constructing abasic_ostream<charT, +traits>::sentry k (os)
. Ifbool(k)
is +true
,sentry
object, if +this object returnstrue
when converted to a value of +typebool
, determines padding as described in +22.2.2.2.2, then inserts the resulting sequence of characters +seq
as if by callingos.rdbuf()->sputn(seq , +n)
, wheren
is the larger of +os.width()
andstr.size()
; then calls +os.width(0)
.If the call to sputn fails, calls ++ +os.setstate(ios_base::failbit)
.
+
+This proposed resilution assumes the resolution of issue 394 (i.e.,
+that all formatted output functions are required to set
+ios_base::badbit
in response to any kind of streambuf
+failure), and implicitly assumes that a return value of
+sputn(seq, n)
other than n
+indicates a failure.
+
+
Section: 23.1 [container.requirements] Status: WP + Submitter: Peter Dimov Date: 2006-08-02
+View other active issues in [container.requirements].
+View all other issues in [container.requirements].
+View all issues with WP status.
+Duplicate of: 536
+Discussion:
++There appears to be no requirements on the InputIterators used in sequences in 23.1.1 in +terms of their value_type, and the requirements in 23.1.2 appear to be overly strict +(requires InputIterator::value_type be the same type as the container's value_type). +
+ + +Proposed resolution:
++Change 23.1.1 p3: +
+ ++ ++In Tables 82 and 83, X denotes a sequence class, a denotes a +value of X, i and j denote iterators satisfying input +iterator requirements and refer to elements implicitly +convertible to value_type, [i, j) denotes a valid +range, n denotes a value of X::size_type, p denotes a +valid iterator to a, q denotes a valid dereferenceable +iterator to a, [q1, q2) denotes a valid range in a, +and t denotes a value of X::value_type. +
+Change 23.1.2 p7: +
+ ++ + + ++In Table 84, X is an associative container class, a is a value +of X, a_uniq is a value of X when X supports +unique keys, and a_eq is a value of X when X supports +multiple keys, i and j satisfy input iterator requirements and +refer to elements
ofimplicitly convertible to +value_type, [i, j) is a valid range, p is a valid +iterator to a, q is a valid dereferenceable iterator to +a, [q1, q2) is a valid range in a, t is a +value of X::value_type, k is a value of X::key_type +and c is a value of type X::key_compare. +
Rationale:
++Concepts will probably come in and rewrite this section anyway. But just in case it is +easy to fix this up as a safety net and as a clear statement of intent. +
+ + + + + +Section: 18.3 [cstdint], TR1 8.22 [tr.c99.cstdint] Status: WP + Submitter: Walter Brown Date: 2006-08-28
+View all other issues in [cstdint].
+View all issues with WP status.
+Discussion:
++Clause 18.3 of the current Working Paper (N2009) deals with the new C++ headers +<cstdint> and <stdint.h>. These are of course based on the C99 header +<stdint.h>, and were part of TR1. +
+ ++Per 18.3.1/1, these headers define a number of macros and function macros. +While the WP does not mention __STDC_CONSTANT_MACROS in this context, C99 +footnotes do mention __STDC_CONSTANT_MACROS. Further, 18.3.1/2 states that "The +header defines all ... macros the same as C99 subclause 7.18." +
+ ++Therefore, if I wish to have the above-referenced macros and function macros +defined, must I #define __STDC_CONSTANT_MACROS before I #include <cstdint>, or +does the C++ header define these macros/function macros unconditionally? +
+ + +Proposed resolution:
++To put this issue to rest for C++0X, I propose the following addition to +18.3.1/2 of the Working Paper N2009: +
+ ++ + + + + ++[Note: The macros defined by <cstdint> are provided unconditionally: in +particular, the symbols __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS +(mentioned in C99 footnotes 219, 220, and 222) play no role in C++. --end note] +
Section: 26.3.7 [complex.value.ops] Status: WP + Submitter: Stefan Große Pawig Date: 2006-09-24
+View all other issues in [complex.value.ops].
+View all issues with WP status.
+Discussion:
++TR1 introduced, in the C compatibility chapter, the function +fabs(complex<T>): +
++ +----- SNIP ----- +8.1.1 Synopsis [tr.c99.cmplx.syn] + + namespace std { + namespace tr1 { +[...] + template<class T> complex<T> fabs(const complex<T>& x); + } // namespace tr1 + } // namespace std + +[...] + +8.1.8 Function fabs [tr.c99.cmplx.fabs] + +1 Effects: Behaves the same as C99 function cabs, defined in + subclause 7.3.8.1. +----- SNIP ----- +
+The current C++0X draft document (n2009.pdf) adopted this +definition in chapter 26.3.1 (under the comment // 26.3.7 values) +and 26.3.7/7. +
++But in C99 (ISO/IEC 9899:1999 as well as the 9899:TC2 draft document +n1124), the referenced subclause reads +
+ ++ +----- SNIP ----- +7.3.8.1 The cabs functions + + Synopsis + +1 #include <complex.h> + double cabs(double complex z); + float cabsf(float complex z); + long double cabsl(long double z); + + Description + +2 The cabs functions compute the complex absolute value (also called + norm, modulus, or magnitude) of z. + + Returns + +3 The cabs functions return the complex absolute value. +----- SNIP ----- +
+Note that the return type of the cabs*() functions is not a complex +type. Thus, they are equivalent to the already well established + template<class T> T abs(const complex<T>& x); +(26.2.7/2 in ISO/IEC 14882:1998, 26.3.7/2 in the current draft +document n2009.pdf). +
++So either the return value of fabs() is specified wrongly, or fabs() +does not behave the same as C99's cabs*(). +
+ +Possible Resolutions + ++This depends on the intention behind the introduction of fabs(). +
++If the intention was to provide a /complex/ valued function that +calculates the magnitude of its argument, this should be +explicitly specified. In TR1, the categorization under "C +compatibility" is definitely wrong, since C99 does not provide +such a complex valued function. +
++Also, it remains questionable if such a complex valued function +is really needed, since complex<T> supports construction and +assignment from real valued arguments. There is no difference +in observable behaviour between +
++complex<double> x, y; + y = fabs(x); + complex<double> z(fabs(x)); +
+and +
++complex<double> x, y; + y = abs(x); + complex<double> z(abs(x)); +
+If on the other hand the intention was to provide the intended +functionality of C99, fabs() should be either declared deprecated +or (for C++0X) removed from the standard, since the functionality +is already provided by the corresponding overloads of abs(). +
+ +[ +Bellevue: +]
+ + ++Bill believes that abs() is a suitable overload. We should remove fabs(). ++ + +
Proposed resolution:
+ ++Change the synopsis in 26.3.1 [complex.synopsis]: +
+ ++ +template<class T> complex<T> fabs(const complex<T>&);+
+Remove 26.3.7 [complex.value.ops], p7: +
+ +++ + + ++template<class T> complex<T> fabs(const complex<T>& x);++++
+-7- Effects: Behaves the same as C99 function cabs, defined in subclause 7.3.8.1.+
[ +Kona (2007): Change the return type of fabs(complex) to T. +Proposed Disposition: Ready +]
+ + + + + +Section: 27.8.1.4 [filebuf.members] Status: WP + Submitter: Thomas Plum Date: 2006-09-26
+View all other issues in [filebuf.members].
+View all issues with WP status.
+Discussion:
++In testing 27.8.1.4 [filebuf.members], Table 112 (in the latest N2009 draft), we invoke +
++ostr.open("somename", ios_base::out | ios_base::in | ios_base::app) +
+and we expect the open to fail, because out|in|app is not listed in +Table 92, and just before the table we see very specific words: +
+++ If mode is not some combination of flags shown in the table + then the open fails. +
+But the corresponding table in the C standard, 7.19.5.3, provides two +modes "a+" and "a+b", to which the C++ modes out|in|app and +out|in|app|binary would presumably apply. +
++We would like to argue that the intent of Table 112 was to match the +semantics of 7.19.5.3 and that the omission of "a+" and "a+b" was +unintentional. (Otherwise there would be valid and useful behaviors +available in C file I/O which are unavailable using C++, for no +valid functional reason.) +
++We further request that the missing modes be explicitly restored to +the WP, for inclusion in C++0x. +
+ +[ +Martin adds: +]
+ + ++...besides "a+" and "a+b" the C++ table is also missing a row +for a lone app bit which in at least two current implementation +as well as in Classic Iostreams corresponds to the C stdio "a" +mode and has been traditionally documented as implying ios::out. +Which means the table should also have a row for in|app meaning +the same thing as "a+" already proposed in the issue. +
+ + +Proposed resolution:
++Add to the table "File open modes" in 27.8.1.4 [filebuf.members]: +
+ +++ + + ++
+File open modes ++ +ios_base Flag combination +stdio equivalent ++ + +binary in out trunc app + + ++ "w" ++ ++ + "a" ++ ++ "a" ++ ++ + "w" ++ ++ "r" ++ ++ + "r+" ++ ++ + + "w+" ++ ++ + + "a+" ++ + ++ + "a+" ++ ++ + "wb" ++ ++ + + "ab" ++ ++ + "ab" ++ ++ + + "wb" ++ ++ + "rb" ++ ++ + + "r+b" ++ + + + + "w+b" ++ ++ + + + "a+b" ++ + + ++ + + "a+b" +
[ +Kona (2007) Added proposed wording and moved to Review. +]
+ + + + + +Section: TRDecimal 3.2 [trdec.types.types] Status: TRDec + Submitter: Daniel Krugler Date: 2006-05-28
+View other active issues in [trdec.types.types].
+View all other issues in [trdec.types.types].
+View all issues with TRDec status.
+Discussion:
+ ++In a private email, Daniel writes: +
++++I would like to +ask, what where the reason for the decision to +define the semantics of the integral conversion of the decimal types, namely +
+"operator long long() const; + + Returns: Returns the result of the +conversion of *this to the type long long, as if +performed by the expression llrounddXX(*this)." +++where XX stands for either 32, 64, or 128, +corresponding to the proper decimal type. The +exact meaning of llrounddXX is not given in that +paper, so I compared it to the corresponding +definition given in C99, 2nd edition (ISO 9899), which says in 7.12.9.7 p. 2: +
++"The lround and llround functions round their +argument to the nearest integer value, +rounding halfway cases away from zero, regardless +of the current rounding direction. [..]" +
++Now considering the fact that integral conversion +of the usual floating-point types ("4.9 +Floating-integral conversions") has truncation +semantic I wonder why this conversion behaviour +has not been transferred for the decimal types. +
+
+Robert comments: +
+
+Also, there is a further error in the Returns: clause for converting decimal::decimal128
to long long
. It currently calls llroundd64
, not llroundd128
.
+
Proposed resolution:
++Change the Returns: clause in 3.2.2.4 to: +
+++Returns: Returns the result of the conversion of
*this
to the typelong long
, as if performed by the expressionllroundd32(*this)
while the decimal rounding direction mode [3.5.2]FE_DEC_TOWARD_ZERO
is in effect. +
+Change the Returns: clause in 3.2.3.4 to: +
+++Returns: Returns the result of the conversion of
*this
to the typelong long
, as if performed by the expressionllroundd64(*this)
while the decimal rounding direction mode [3.5.2]FE_DEC_TOWARD_ZERO
is in effect. +
+Change the Returns: clause in 3.2.4.4 to: +
++ + + + + + ++Returns: Returns the result of the conversion of
*this
to the typelong long
, as if performed by the expressionllroundd64(*this)
llroundd128(*this)
while the decimal rounding direction mode [3.5.2]FE_DEC_TOWARD_ZERO
is in effect. +
Section: TRDecimal 3.1 [trdec.types.encodings] Status: TRDec + Submitter: Daniel Krugler Date: 2006-05-28
+View all issues with TRDec status.
+Discussion:
++Daniel writes in a private email: +
+ +++ + ++- 3.1 'Decimal type encodings' says in its note: +
+"this implies that +sizeof(std::decimal::decimal32) == 4, +sizeof(std::decimal::decimal64) == 8, and +sizeof(std::decimal::decimal128) == 16." +++This is a wrong assertion, because the definition +of 'byte' in 1.7 'The C+ + memory model' of ISO +14882 (2nd edition) does not specify that a byte +must be necessarily 8 bits large, which would be +necessary to compare with the specified bit sizes +of the types decimal32, decimal64, and decimal128. +
+
Proposed resolution:
++Change 3.1 as follows: +
+++ + + + ++The three decimal encoding formats defined in IEEE-754R correspond to the three decimal floating types as follows: +
++
+- +decimal32 is a decimal32 number, which is encoded in four consecutive
+bytesoctets (32 bits) +- +decimal64 is a decimal64 number, which is encoded in eight consecutive
+bytesoctets (64 bits) + +- +decimal128 is a decimal128 number, which is encoded in 16 consecutive
+bytesoctets (128 bits) ++
+[Note: this implies that+sizeof(std::decimal::decimal32) == 4
,sizeof(std::decimal::decimal64) == 8
, andsizeof(std::decimal::decimal128) == 16
. --end note]
Section: TRDecimal 3.9 [trdec.types.cwchar] Status: TRDec + Submitter: Daniel Krugler Date: 2006-05-28
+View all issues with TRDec status.
+Discussion:
++Daniel writes: +
++ + ++- 3.9.1 'Additions to <cwchar>' provides wrong +signatures to the wcstod32, wcstod64, and +wcstod128 functions ([the parameters have type pointer-to-] char instead of wchar_t). +
Proposed resolution:
+
+Change "3.9.1 Additions to <cwchar>
synopsis" to:
+
namespace std { + namespace decimal { + // 3.9.2 wcstod functions: + decimal32 wcstod32 (const+ + + + +charwchar_t * nptr,charwchar_t ** endptr); + decimal64 wcstod64 (constcharwchar_t * nptr,charwchar_t ** endptr); + decimal128 wcstod128 (constcharwchar_t * nptr,charwchar_t ** endptr); + } + } +
Section: TRDecimal 3.3 [trdec.types.limits] Status: TRDec + Submitter: Daniel Krugler Date: 2006-05-28
+View all issues with TRDec status.
+Discussion:
++Daniel writes in a private email: +
+ +++ + ++- 3.3 'Additions to header <limits>' contains two +errors in the specialisation of numeric_limits<decimal::decimal128>: +
++
+- The static member max() returns DEC128_MIN, this should be DEC128_MAX.
+- The static member digits is assigned to 384, +this should be 34 (Probably mixed up with the +max. exponent for decimal::decimal64).
+
Proposed resolution:
+
+In "3.3 Additions to header <limits>
" change numeric_limits<decimal::decimal128> as follows:
+
template<> class numeric_limits<decimal::decimal128> { + public: + static const bool is_specialized = true; + + static decimal::decimal128 min() throw() { return DEC128_MIN; } + static decimal::decimal128 max() throw() { return+ + + + +DEC128_MIN;DEC128_MAX; } + + static const int digits =38434; + /* ... */ +
Section: TRDecimal 3 [trdec.types] Status: TRDec + Submitter: Daniel Krugler Date: 2006-05-28
+View all other issues in [trdec.types].
+View all issues with TRDec status.
+Discussion:
++The document uses the term "generic floating types," but defines it nowhere. +
+ + +Proposed resolution:
++Change the first paragraph of "3 Decimal floating-point types" as follows: +
++ + + + ++This Technical Report introduces three decimal floating-point types, named +decimal32, decimal64, and decimal128. The set of values of type decimal32 is a +subset of the set of values of type decimal64; the set of values of the type +decimal64 is a subset of the set of values of the type decimal128. Support for +decimal128 is optional. These types supplement the Standard C++ types +
float
,double
, andlong double
, which are +collectively described as the basic floating types. +
Section: TRDecimal 3 [trdec.types] Status: TRDec + Submitter: Martin Sebor Date: 2006-05-28
+View all other issues in [trdec.types].
+View all issues with TRDec status.
+Discussion:
+In c++std-lib-17198, Martin writes:
+ ++ + ++Each of the three classes proposed in the paper (decimal32, decimal64, +and decimal128) explicitly declares and specifies the semantics of its +copy constructor, copy assignment operator, and destructor. Since the +semantics of all three functions are identical to the trivial versions +implicitly generated by the compiler in the absence of any declarations +it is safe to drop them from the spec. This change would make the +proposed classes consistent with other similar classes already in the +standard (e.g., std::complex). +
Proposed resolution:
+
+Change "3.2.2 Class decimal32
" as follows:
+
namespace std { + namespace decimal { + class decimal32 { + public: + // 3.2.2.1 construct/copy/destroy: + decimal32(); ++decimal32(const decimal32 & d32);+decimal32 & operator=(const decimal32 & d32);+~decimal32();+ /* ... */ +
+Change "3.2.2.1 construct/copy/destroy" as follows: +
+decimal32(); + + Effects: Constructs an object of type decimal32 with the value 0; + ++decimal32(const decimal32 & d32);+decimal32 & operator=(const decimal32 & d32);+ +Effects: Copies an object of type decimal32.+ +~decimal32();+ +Effects: Destroys an object of type decimal32.+ +
+Change "3.2.3 Class decimal64
" as follows:
+
namespace std { + namespace decimal { + class decimal64 { + public: + // 3.2.3.1 construct/copy/destroy: + decimal64(); ++decimal64(const decimal64 & d64);+decimal64 & operator=(const decimal64 & d64);+~decimal64();+ /* ... */ +
+Change "3.2.3.1 construct/copy/destroy" as follows: +
+decimal64(); + + Effects: Constructs an object of type decimal64 with the value 0; + ++decimal64(const decimal64 & d64);+decimal64 & operator=(const decimal64 & d64);+ +Effects: Copies an object of type decimal64.+ +~decimal64();+ +Effects: Destroys an object of type decimal64.+ +
+Change "3.2.4 Class decimal128
" as follows:
+
namespace std { + namespace decimal { + class decimal128 { + public: + // 3.2.4.1 construct/copy/destroy: + decimal128(); ++decimal128(const decimal128 & d128);+decimal128 & operator=(const decimal128 & d128);+~decimal128();+ /* ... */ +
+Change "3.2.4.1 construct/copy/destroy" as follows: +
+decimal128(); + + Effects: Constructs an object of type decimal128 with the value 0; + ++ + + + +decimal128(const decimal128 & d128);+decimal128 & operator=(const decimal128 & d128);+ +Effects: Copies an object of type decimal128.+ +~decimal128();+ +Effects: Destroys an object of type decimal128.+ +
Section: TRDecimal 3 [trdec.types] Status: TRDec + Submitter: Martin Sebor Date: 2006-05-28
+View all other issues in [trdec.types].
+View all issues with TRDec status.
+Discussion:
++In c++std-lib-17197, Martin writes: +
+++The extended_num_get and extended_num_put facets are designed +to store a reference to a num_get or num_put facet which the +extended facets delegate the parsing and formatting of types +other than decimal. One form of the extended facet's ctor (the +default ctor and the size_t overload) obtains the reference +from the global C++ locale while the other form takes this +reference as an argument. +
++The problem with storing a reference to a facet in another +object (as opposed to storing the locale object in which the +facet is installed) is that doing so bypasses the reference +counting mechanism designed to prevent a facet that is still +being referenced (i.e., one that is still installed in some +locale) from being destroyed when another locale that contains +it is destroyed. Separating a facet reference from the locale +it comes from van make it cumbersome (and in some cases might +even make it impossible) for programs to prevent invalidating +the reference. (The danger of this design is highlighted in +the paper.) +
+ + ++This problem could be easily avoided by having the extended +facets store a copy of the locale from which they would extract +the base facet either at construction time or when needed. To +make it possible, the forms of ctors of the extended facets that +take a reference to the base facet would need to be changed to +take a locale argument instead. +
Proposed resolution:
+
+1. Change the extended_num_get
synopsis in 3.10.2 as follows:
+
extended_num_get(const+std::num_get<charT, InputIterator>std::locale & b, size_t refs = 0); + + /* ... */ + +// const std::num_get<charT, InputIterator> & base; exposition only+ // std::locale baseloc; exposition only +
+2. Change the description of the above constructor in 3.10.2.1: +
+extended_num_get(const+std::num_get<charT, InputIterator>std::locale & b, size_t refs = 0); + +
+++Effects: Constructs an
+extended_num_get
facet as if by: +extended_num_get(const+std::num_get<charT, InputIterator>std::locale & b, size_t refs = 0) + : facet(refs), baseloc(b) + { /* ... */ } + ++
+Notes: Care must be taken by the implementation to ensure that the lifetime of the facet referenced by base exceeds that of the resulting+extended_num_get
facet.
+3. Change the Returns: clause for do_get(iter_type, iter_type, ios_base &, ios_base::iostate &, bool &) const
, et al to
+
++Returns:
. +
basestd::use_facet<std::num_get<charT, InputIterator> >(baseloc).get(in, end, str, err, val)
+4. Change the extended_num_put
synopsis in 3.10.3 as follows:
+
extended_num_put(const+std::num_put<charT, OutputIterator>std::locale & b, size_t refs = 0); + + /* ... */ + +// const std::num_put<charT, OutputIterator> & base; exposition only+ // std::locale baseloc; exposition only +
+5. Change the description of the above constructor in 3.10.3.1: +
+extended_num_put(const+std::num_put<charT, OutputIterator>std::locale & b, size_t refs = 0); +
+++Effects: Constructs an
+extended_num_put
facet as if by: +extended_num_put(const+std::num_put<charT, OutputIterator>std::locale & b, size_t refs = 0) + : facet(refs), baseloc(b) + { /* ... */ } + ++
+Notes: Care must be taken by the implementation to ensure that the lifetime of the facet referenced by base exceeds that of the resulting+extended_num_put
facet.
+6. Change the Returns: clause for do_put(iter_type, ios_base &, char_type, bool &) const
, et al to
+
+ ++Returns:
. +
basestd::use_facet<std::num_put<charT, OutputIterator> >(baseloc).put(s, f, fill, val)
[ +Redmond: We would prefer to rename "extended" to "decimal". +]
+ + + + + + +Section: TRDecimal 3.4 [trdec.types.cdecfloat] Status: TRDec + Submitter: Robert Klarer Date: 2006-10-17
+View all issues with TRDec status.
+Discussion:
++In Berlin, WG14 decided to drop the <decfloat.h> header. The +contents of that header have been moved into <float.h>. For the +sake of C compatibility, we should make corresponding changes. +
+ + +Proposed resolution:
+
+1. Change the heading of subclause 3.4, "Headers <cdecfloat>
and <decfloat.h>
" to "Additions to headers <cfloat>
and <float.h>
."
+
+2. Change the text of subclause 3.4 as follows: +
++++
+The standard C++ headers+<cfloat>
and<float.h>
define characteristics of the floating-point typesfloat
,double
, andlong double
. Their contents remain unchanged by this Technical Report.+
+Headers+<cdecfloat>
and<decfloat.h>
define characteristics of the decimal floating-point typesdecimal32
,decimal64
, anddecimal128
. As well,<decfloat.h>
defines the convenience typedefs_Decimal32
,_Decimal64
, and_Decimal128
, for compatibilty with the C programming language.+The header
+<cfloat>
is described in [tr.c99.cfloat]. The header<float.h>
+is described in [tr.c99.floath]. These headers are extended by this +Technical Report to define characteristics of the decimal +floating-point typesdecimal32
,decimal64
, anddecimal128
. As well,<float.h>
is extended to define the convenience typedefs_Decimal32
,_Decimal64
, and_Decimal128
for compatibility with the C programming language. +
+3. Change the heading of subclause 3.4.1, "Header <cdecfloat>
synopsis" to "Additions to header <cfloat>
synopsis."
+
+4. Change the heading of subclause 3.4.2, "Header <decfloat.h>
synopsis" to "Additions to header <float.h>
synopsis."
+
+5. Change the contents of 3.4.2 as follows: +
++ + + + + +#include <cdecfloat>+ + // C-compatibility convenience typedefs: + + typedef std::decimal::decimal32 _Decimal32; + typedef std::decimal::decimal64 _Decimal64; + typedef std::decimal::decimal128 _Decimal128; +
Section: 26.4.7.1 [rand.util.seedseq] Status: WP + Submitter: Charles Karney Date: 2006-10-26
+View other active issues in [rand.util.seedseq].
+View all other issues in [rand.util.seedseq].
+View all issues with WP status.
+Discussion:
++Short seed vectors of 32-bit quantities all result in different states. However +this is not true of seed vectors of 16-bit (or smaller) quantities. For example +these two seeds +
+ ++ +unsigned short seed = {1, 2, 3}; +unsigned short seed = {1, 2, 3, 0}; +
+both pack to +
+ ++ +unsigned seed = {0x20001, 0x3}; +
+yielding the same state. +
+ ++See N2391 and +N2423 +for some further discussion. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2423. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 26.4.7.1 [rand.util.seedseq] Status: WP + Submitter: Charles Karney Date: 2006-10-26
+View other active issues in [rand.util.seedseq].
+View all other issues in [rand.util.seedseq].
+View all issues with WP status.
+Discussion:
++In 26.4.7.1 [rand.util.seedseq] /6, the order of packing the inputs into b and the +treatment of signed quantities is unclear. Better to spell it out. +
+ ++See N2391 and +N2423 +for some further discussion. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2423. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 26.4.4.2 [rand.adapt.ibits], TR1 5.1 [tr.rand] Status: WP + Submitter: Walter E. Brown Date: 2006-11-02
+View all issues with WP status.
+Discussion:
++In preparing N2111, an error on my part resulted in the omission of the +following line from the template synopsis in the cited section: +
+ ++ +static const size_t word_size = w; +
+(This same constant is found, for example, in 26.4.3.3 [rand.eng.sub].) +
+ + +Proposed resolution:
++Add the above declaration as the first line after the comment in [rand.adapt.ibits] p4: +
+ ++ +// engine characteristics +static const size_t word_size = w; +
+and accept my apologies for the oversight. +
+ + + + + +Section: 20.6.15.2.1 [func.wrap.func.con], TR1 3.7.2.1 [tr.func.wrap.func.con] Status: WP + Submitter: Scott Meyers Date: 2006-11-02
+View all issues with WP status.
+Discussion:
++My suggestion is that implementers of both tr1::function and its +official C++0x successor be explicitly encouraged (but not required) to +optimize for the cases mentioned above, i.e., function pointers and +small function objects. They could do this by using a small internal +buffer akin to the buffer used by implementations of the small string +optimization. (That would make this the small functor optimization -- +SFO :-}) The form of this encouragement could be a note in the standard +akin to footnote 214 of the current standard. +
+ ++Dave Abrahams notes: +
+ ++"shall not throw exceptions" should really be "nothing," both to be more +grammatical and to be consistent with existing wording in the standard. +
+ ++Doug Gregor comments: I think this is a good idea. Currently, implementations of +tr1::function are required to have non-throwing constructors and assignment +operators when the target function object is a function pointer or a +reference_wrapper. The common case, however, is for a tr1::function to store +either an empty function object or a member pointer + an object pointer. +
++The function implementation in the upcoming Boost 1.34.0 uses the +"SFO", so that the function objects for typical bind expressions like +
++ +bind(&X::f, this, _1, _2, _3) +
+do not require heap allocation when stored in a boost::function. I +believe Dinkumware's implementation also performs this optimization. +
+ + + +Proposed resolution:
++Revise 20.5.14.2.1 p6 [func.wrap.func.con] to add a note as follows: +
+ +++ + + + + ++Throws: shall not throw exceptions if f's target is a function +pointer or a function object passed via reference_wrapper. Otherwise, +may throw bad_alloc or any exception thrown by the copy constructor of +the stored function object. +
++Note: Implementations are encouraged to avoid the use of dynamically +allocated memory for "small" function objects, e.g., where f's target +is an object holding only a pointer or reference to an object and a member +function pointer (a "bound member function"). +
+
Section: 17.4.3.7 [res.on.functions] Status: WP + Submitter: Nicola Musatti Date: 2006-11-13
+View all issues with WP status.
+Discussion:
++In the latest available draft standard +(N2134) +§ 17.4.3.6 [res.on.functions] states: +
+ +++ ++-1- In certain cases (replacement functions, handler functions, operations on +types used to instantiate standard library template components), the C++ +Standard Library depends on components supplied by a C++ program. If these +components do not meet their requirements, the Standard places no requirements +on the implementation. +
+ ++-2- In particular, the effects are undefined in the following cases: +
++[...] +
++
+- if an incomplete type (3.9) is used as a template argument when +instantiating a template component.
+
+This is contradicted by § 20.6.6.2/2 [util.smartptr.shared] which +states: +
+ +++ + ++[...] +
+ ++The template parameter T of shared_ptr may be an incomplete type. +
+
Proposed resolution:
++Modify the last bullet of § 17.4.3.6/2 [res.on.functions] to allow for +exceptions: +
+ +++ + + + + + ++
+- if an incomplete type (3.9) is used as a template argument when +instantiating a template component, unless specifically allowed for the +component.
+
Section: 18.2.1.2 [numeric.limits.members] Status: WP + Submitter: Chris Jefferson Date: 2006-11-10
+View all other issues in [numeric.limits.members].
+View all issues with WP status.
+Discussion:
++18.2.1.2 55 states that "A type is modulo if it is possible to add two +positive numbers together and have a result that wraps around to a +third number that is less". +This seems insufficient for the following reasons: +
+ +[ +Batavia: Related to +N2144. +Pete: is there an ISO definition of modulo? Underflow on signed behavior is undefined. +]
+ + +[ +Bellevue: accept resolution, move to ready status. +Does this mandate that is_modulo be true on platforms for which int +happens to b modulo? A: the standard already seems to require that. +]
+ + + +Proposed resolution:
++Suggest 18.2.1.2 [numeric.limits.members], paragraph 57 is amended to: +
+ ++ + + + + + ++A type is modulo if,
it is possible to add two positive numbers +and have a result that wraps around to a third number that is less.+given any operation involving +,- or * on values of that type whose value +would fall outside the range [min(), max()], then the value returned +differs from the true value by an integer multiple of (max() - min() + +1). +
Section: 18.2.1.5 [numeric.special] Status: WP + Submitter: Bo Persson Date: 2006-11-20
+View all other issues in [numeric.special].
+View all issues with WP status.
+Discussion:
++Section 18.2.1.5 [numeric.special] starts out by saying that "All members shall be provided +for all specializations." +
++Then it goes on to show specializations for float and bool, where one member +is missing (max_digits10). +
+ ++Maarten Kronenburg adds: +
+ ++I agree, just adding the comment that the exact number of decimal digits +is digits * ln(radix) / ln(10), where probably this real number is +rounded downward for digits10, and rounded upward for max_digits10 +(when radix=10, then digits10=max_digits10). +Why not add this exact definition also to the standard, so the user +knows what these numbers exactly mean. +
+ ++Howard adds: +
+ ++For reference, here are the correct formulas from +N1822: +
+ ++ +digits10 = floor((digits-1) * log10(2)) +max_digits10 = ceil((1 + digits) * log10(2)) +
+We are also missing a statement regarding for what specializations this member has meaning. +
+ + + +Proposed resolution:
++Change and add after 18.2.1.2 [numeric.limits.members], p11: +
+ +++ +static const int max_digits10;++++-11- Number of base 10 digits required to ensure that values which +differ
+by only one epsilonare always differentiated. ++-12- Meaningful for all floating point types. +
+
+Change 18.2.1.5 [numeric.special], p2: +
+ ++ +template<> class numeric_limits<float> { +public: + static const bool is_specialized = true; + ... + static const int digits10 = 6; + static const int max_digits10 = 9; + ... +
+Change 18.2.1.5 [numeric.special], p3: +
+ ++ + + + + + + +template<> class numeric_limits<bool> { +public: + static const bool is_specialized = true; + ... + static const int digits10 = 0; + static const int max_digits10 = 0; + ... +
Section: 22.2.1.2 [locale.ctype.byname] Status: WP + Submitter: Bo Persson Date: 2006-12-16
+View all other issues in [locale.ctype.byname].
+View all issues with WP status.
+Discussion:
++Section 22.2.1.2 defines the ctype_byname class template. It contains the +line +
+ ++ + + +typedef ctype<charT>::mask mask; +
Proposed resolution:
++as this is a dependent type, it should obviously be +
+ ++ + + + + +typedef typename ctype<charT>::mask mask; +
Section: 26.5.2.7 [valarray.members] Status: WP + Submitter: Gabriel Dos Reis Date: 2007-01-10
+View all issues with WP status.
+Discussion:
++I would respectfully request an issue be opened with the intention to +clarify the wording for size() == 0 for cshift. +
+ + +Proposed resolution:
++Change 26.5.2.7 [valarray.members], paragraph 10: +
+ ++ ++ + + +valarray<T> cshift(int n) const; ++ ++++This function returns an object of class valarray<T>, of +length size(),
+each of whose elements I is +(*this)[(I + n ) % size()]. Thus, if element zero is taken as +the leftmost element, a positive value of n shifts the elements +circularly left n places.that is a circular shift of *this. If +element zero is taken as the leftmost element, a non-negative value of +n shifts the elements circularly left n places and a +negative value of n shifts the elements circularly right +-n places. +
Rationale:
++We do not believe that there is any real ambiguity about what happens +when size() == 0, but we do believe that spelling this out as a C++ +expression causes more trouble that it solves. The expression is +certainly wrong when n < 0, since the sign of % with negative arguments +is implementation defined. +
+ + +[ +Kona (2007) Changed proposed wording, added rationale and set to Review. +]
+ + + + + +Section: 18.9 [support.runtime] Status: WP + Submitter: Lawrence Crowl Date: 2007-01-12
+View all issues with WP status.
+Discussion:
++The wording for longjmp is confusing. +
++18.9 [support.runtime] -4- Other runtime support +
+++The function signature longjmp(jmp_buf jbuf, int val) has more restricted +behavior in this International Standard. If any automatic objects would +be destroyed by a thrown exception transferring control to another +(destination) point in the program, then a call to longjmp(jbuf, val) that +the throw point that transfers control to the same (destination) point has +undefined behavior. +
+Someone at Google thinks that should say "then a call to longjmp(jbuf, val) +*at* the throw point that transfers control". +
++Bill Gibbons thinks it should say something like "If any automatic objects +would be destroyed by an exception thrown at the point of the longjmp and +caught only at the point of the setjmp, the behavior is undefined." +
+ + +Proposed resolution:
++In general, accept Bill Gibbons' recommendation, +but add "call" to indicate that the undefined behavior +comes from the dynamic call, not from its presence in the code. +In 18.9 [support.runtime] paragraph 4, change +
+ ++ + + + + ++The function signature longjmp(jmp_buf jbuf, int val) has more +restricted behavior in this International Standard.
If any automatic +objects would be destroyed by a thrown exception transferring control to another +(destination) point in the program, then a call to longjmp(jbuf, val) +that the throw point that transfers control to the same (destination) point has +undefined behavior.A setjmp/longjmp call pair has +undefined behavior if replacing the setjmp and longjmp by +catch and throw would destroy any automatic objects. +
Section: 26.5.2.1 [valarray.cons] Status: WP + Submitter: Martin Sebor Date: 2007-01-20
+View other active issues in [valarray.cons].
+View all other issues in [valarray.cons].
+View all issues with WP status.
+Discussion:
+
+
+The Effects clause for the default valarray
ctor
+suggests that it is possible to increase the size of an empty
+valarray
object by calling other non-const member
+functions of the class besides resize()
. However, such an
+interpretation would be contradicted by the requirement on the copy
+assignment operator (and apparently also that on the computed
+assignments) that the assigned arrays be the same size. See the
+reflector discussion starting with c++std-lib-17871.
+
+
+ +In addition, Footnote 280 uses some questionable normative +language. + +
+ + +Proposed resolution:
++ +Reword the Effects clause and Footnote 280 as follows (26.5.2.1 [valarray.cons]): + +
+++ + + + + ++ +
+valarray();
+ ++ +Effects: Constructs an object of class +
+valarray<T>
,279) which has zero +lengthuntil it is passed into a library function as a modifiable +lvalue or through a non-constant this pointer.280) + ++ +Postcondition:
+size() == 0
. + ++ +Footnote 280: This default constructor is essential, since +arrays of
+valarray
are likely to prove useful. +There shall also be a way to change the size of an array after +initialization; this is supplied by the semanticsmay be +useful. The length of an empty array can be increased after +initialization by means of theresize()
member +function. + +
Section: 26.5 [numarray] Status: WP + Submitter: Martin Sebor Date: 2007-01-20
+View all other issues in [numarray].
+View all issues with WP status.
+Discussion:
+
+
+The computed and "fill" assignment operators of valarray
+helper array class templates (slice_array
,
+gslice_array
, mask_array
, and
+indirect_array
) are const member functions of each class
+template (the latter by the resolution of 123
+since they have reference semantics and thus do not affect
+the state of the object on which they are called. However, the copy
+assignment operators of these class templates, which also have
+reference semantics, are non-const. The absence of constness opens
+the door to speculation about whether they really are intended to have
+reference semantics (existing implementations vary widely).
+
+
+Pre-Kona, Martin adds: +
+ ++I realized that adding the const qualifier to the +functions as I suggested would break the const correctness of the +classes. A few possible solutions come to mind: +
+ +Proposed resolution:
++ +Declare the copy assignment operators of all four helper array +class templates const. + +
++ +Specifically, make the following edits: + +
++ +Change the signature in 26.5.5 [template.slice.array] and +26.5.5.1 [slice.arr.assign] as follows: + +
+++const slice_array& operator= (const slice_array&) const;
+ +
+ +Change the signature in 26.5.7 [template.gslice.array] and +26.5.7.1 [gslice.array.assign] as follows: + +
+++const gslice_array& operator= (const gslice_array&) const;
+ +
+ +Change the signature in 26.5.8 [template.mask.array] and 26.5.8.1 [mask.array.assign] as +follows: + +
+++const mask_array& operator= (const mask_array&) const;
+ +
+ +Change the signature in 26.5.9 [template.indirect.array] and +26.5.9.1 [indirect.array.assign] as follows: + +
++ + ++const indirect_array& operator= (const indirect_array&) const;
+ +
[ +Kona (2007) Added const qualification to the return types and set to Ready. +]
+ + + + + +filebuf
dtor and close
on errorSection: 27.8.1.17 [fstream.members] Status: WP + Submitter: Martin Sebor Date: 2007-01-20
+View all issues with WP status.
+Discussion:
+
+
+basic_filebuf
dtor is specified to have the following
+straightforward effects:
+
+
++ +Effects: Destroys an object of class +
basic_filebuf
. Callsclose()
. + +
+
+close()
does a lot of potentially complicated processing,
+including calling overflow()
to write out the termination
+sequence (to bring the output sequence to its initial shift
+state). Since any of the functions called during the processing can
+throw an exception, what should the effects of an exception be on the
+dtor? Should the dtor catch and swallow it or should it propagate it
+to the caller? The text doesn't seem to provide any guidance in this
+regard other than the general restriction on throwing (but not
+propagating) exceptions from destructors of library classes in
+17.4.4.9 [res.on.exception.handling].
+
+
+
+Further, the last thing close()
is specified to do is
+call fclose()
to close the FILE
pointer. The
+last sentence of the Effects clause reads:
+
+
++ +... If any of the calls to
overflow
or +std::fclose
fails thenclose
fails. + +
+
+This suggests that close()
might be required to call
+fclose()
if and only if none of the calls to
+overflow()
fails, and avoid closing the FILE
+otherwise. This way, if overflow()
failed to flush out
+the data, the caller would have the opportunity to try to flush it
+again (perhaps after trying to deal with whatever problem may have
+caused the failure), rather than losing it outright.
+
+
+
+On the other hand, the function's Postcondition specifies that
+is_open() == false
, which suggests that it should call
+fclose()
unconditionally. However, since
+Postcondition clauses are specified for many functions in the
+standard, including constructors where they obviously cannot apply
+after an exception, it's not clear whether this Postcondition
+clause is intended to apply even after an exception.
+
+
+
+It might be worth noting that the traditional behavior (Classic
+Iostreams fstream::close()
and C fclose()
)
+is to close the FILE
unconditionally, regardless of
+errors.
+
+
[ +See 397 and 418 for related issues. +]
+ + + + +Proposed resolution:
+
+
+After discussing this on the reflector (see the thread starting with
+c++std-lib-17650) we propose that close()
be clarified to
+match the traditional behavior, that is to close the FILE
+unconditionally, even after errors or exceptions. In addition, we
+propose the dtor description be amended so as to explicitly require it
+to catch and swallow any exceptions thrown by close()
.
+
+
+ +Specifically, we propose to make the following edits in +27.8.1.4 [filebuf.members]: + +
+++++basic_filebuf<charT,traits>* close();
+ ++ +Effects: If
+is_open() == false
, returns a null +pointer. If a put area exists, calls +overflow(traits::eof())
to flush characters. If the last +virtual member function called on*this
(between +underflow
,overflow
,seekoff
, +andseekpos
) wasoverflow
then calls +a_codecvt.unshift
(possibly several times) to determine a +termination sequence, inserts those characters and calls +overflow(traits::eof())
again. Finally, regardless +of whether any of the preceding calls fails or throws an exception, +the functionitcloses the file ("as if" by calling +std::fclose(file)
).334) If any of the calls +made by the functionto, includingoverflow
+orstd::fclose
, +fails thenclose
fails by returning a null pointer. +If one of these calls throws an exception, the exception is caught and +rethrown after closing the file. + +
+ +And to make the following edits in 27.8.1.2 [filebuf.cons]. + +
+++ + + + + +++virtual ~basic_filebuf();
+ ++ +Effects: Destroys an object of class +
+basic_filebuf<charT,traits>
. Calls +close()
. If an exception occurs during the +destruction of the object, including the call toclose()
, +the exception is caught but not rethrown (see +17.4.4.9 [res.on.exception.handling]). + +
pubimbue
forbidden to call imbue
Section: 27.1.1 [iostream.limits.imbue] Status: WP + Submitter: Martin Sebor Date: 2007-01-20
+View all issues with WP status.
+Discussion:
+
+
+27.1.1 [iostream.limits.imbue] specifies that "no function described in
+clause 27 except for ios_base::imbue
causes any instance
+of basic_ios::imbue
or
+basic_streambuf::imbue
to be called."
+
+
+
+That contradicts the Effects clause for
+basic_streambuf::pubimbue()
which requires the function
+to do just that: call basic_streambuf::imbue()
.
+
+
Proposed resolution:
+
+
+To fix this, rephrase the sentence above to allow
+pubimbue
to do what it was designed to do. Specifically.
+change 27.1.1 [iostream.limits.imbue], p1 to read:
+
+
+ + + + + ++ +No function described in clause 27 except for +
ios_base::imbue
andbasic_filebuf::pubimbue
+causes any instance ofbasic_ios::imbue
or +basic_streambuf::imbue
to be called. ... + +
valarray
assignment and arrays of unequal lengthSection: 26.5.2.2 [valarray.assign] Status: WP + Submitter: Martin Sebor Date: 2007-01-20
+View all issues with WP status.
+Discussion:
+
+
+The behavior of the valarray
copy assignment operator is
+defined only when both sides have the same number of elements and the
+spec is explicit about assignments of arrays of unequal lengths having
+undefined behavior.
+
+
+
+However, the generalized subscripting assignment operators overloaded
+on slice_array
et al (26.5.2.2 [valarray.assign]) don't have any
+such restriction, leading the reader to believe that the behavior of
+these overloads is well defined regardless of the lengths of the
+arguments.
+
+
+ +For example, based on the reading of the spec the behavior of the +snippet below can be expected to be well-defined: + +
+const std::slice from_0_to_3 (0, 3, 1); // refers to elements 0, 1, 2 + const std::valarray<int> a (1, 3); // a = { 1, 1, 1 } + std::valarray<int> b (2, 4); // b = { 2, 2, 2, 2 } + + b = a [from_0_to_3]; ++
+
+In practice, b
may end up being { 1, 1, 1 }
,
+{ 1, 1, 1, 2 }
, or anything else, indicating that
+existing implementations vary.
+
+
+Quoting from Section 3.4, Assignment operators, of Al Vermeulen's +Proposal for Standard C++ Array Classes (see c++std-lib-704; +N0308): +
++ ++ ...if the size of the array on the right hand side of the equal + sign differs from the size of the array on the left, a run time + error occurs. How this error is handled is implementation + dependent; for compilers which support it, throwing an exception + would be reasonable. +
+And see more history in +N0280. +
+ +
+
+It has been argued in discussions on the committee's reflector that
+the semantics of all valarray
assignment operators should
+be permitted to be undefined unless the length of the arrays being
+assigned is the same as the length of the one being assigned from. See
+the thread starting at c++std-lib-17786.
+
+
+ +In order to reflect such views, the standard must specify that the +size of the array referred to by the argument of the assignment must +match the size of the array under assignment, for example by adding a +Requires clause to 26.5.2.2 [valarray.assign] as follows: + +
++ ++ +Requires: The length of the array to which the argument refers +equals
size()
. + +
+
+Note that it's far from clear that such leeway is necessary in order
+to implement valarray
efficiently.
+
+
Proposed resolution:
++Insert new paragraph into 26.5.2.2 [valarray.assign]: +
+ +++ + + + + +valarray<T>& operator=(const slice_array<T>&); +valarray<T>& operator=(const gslice_array<T>&); +valarray<T>& operator=(const mask_array<T>&); +valarray<T>& operator=(const indirect_array<T>&); +++++Requires: The length of the array to which the argument refers +equals
+size()
. ++These operators allow the results of a generalized subscripting operation to be assigned directly to a valarray. +
+
Section: 28.8 [re.regex] Status: WP + Submitter: Bo Persson Date: 2007-01-23
+View all other issues in [re.regex].
+View all issues with WP status.
+Discussion:
++Section 28.8 [re.regex] lists a constructor +
+ ++ +template<class InputIterator> +basic_regex(InputIterator first, InputIterator last, + flag_type f = regex_constants::ECMAScript); +
+However, in section 28.8.2 [re.regex.construct], this constructor takes a +pair of ForwardIterator. +
+ + +Proposed resolution:
++Change 28.8.2 [re.regex.construct]: +
+ ++ + + + + + +template <classForwardIteratorInputIterator> + basic_regex(ForwardIteratorInputIterator first,ForwardIteratorInputIterator last, + flag_type f = regex_constants::ECMAScript); +
Section: 20.7.5.1 [allocator.members] Status: WP + Submitter: Howard Hinnant Date: 2007-02-07
+View all other issues in [allocator.members].
+View all issues with WP status.
+Duplicate of: 350
+Discussion:
+ ++20.7.5.1 [allocator.members] says: +
+++ +pointer address(reference x) const;++++-1- Returns: &x. +
+
+20.7.5.1 [allocator.members] defines CopyConstructible which currently not +only defines the semantics of copy construction, but also restricts what an overloaded +operator& may do. I believe proposals are in the works (such as concepts +and rvalue reference) to decouple these two requirements. Indeed it is not evident +that we should disallow overloading operator& to return something other +than the address of *this. +
+ ++An example of when you want to overload operator& to return something +other than the object's address is proxy references such as vector<bool> +(or its replacement, currently code-named bit_vector). Taking the address of +such a proxy reference should logically yield a proxy pointer, which when dereferenced, +yields a copy of the original proxy reference again. +
+ ++On the other hand, some code truly needs the address of an object, and not a proxy +(typically for determining the identity of an object compared to a reference object). +boost has long recognized this dilemma and solved it with +boost::addressof. +It appears to me that this would be useful functionality for the default allocator. Adopting +this definition for allocator::address would free the standard of requiring +anything special from types which overload operator&. Issue 580 +is expected to make use of allocator::address mandatory for containers. +
+ + + +Proposed resolution:
++Change 20.7.5.1 [allocator.members]: +
+ +++ +pointer address(reference x) const;+++ ++-1- Returns:
+&x.The actual address of object referenced by x, +even in the presence of an overloaded operator&. +const_pointer address(address(const_reference x) const;++++-2- Returns:
+&x.The actual address of object referenced by x, +even in the presence of an overloaded operator&. +
[ +post Oxford: This would be rendered NAD Editorial by acceptance of +N2257. +]
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2387 for this issue which +was subsequently split out into a separate paper N2436 for the purposes of voting. +The resolution in N2436 addresses this issue. The LWG voted to accelerate this +issue to Ready status to be voted into the WP at Kona. +]
+ + + + + + + +Section: 23.2.2.3 [deque.modifiers] Status: WP + Submitter: Steve LoBasso Date: 2007-02-17
+View all issues with WP status.
+Discussion:
++The standard states at 23.2.2.3 [deque.modifiers]/4: +
++deque erase(...) +++Effects: ... An erase at either end of the deque invalidates only +the iterators and the references to the erased elements. +
+
+This does not state that iterators to end will be invalidated. +It needs to be amended in such a way as to account for end invalidation. +
++Something like: +
++ ++Any time the last element is erased, iterators to end are invalidated. +
+This would handle situations like: +
++ +erase(begin(), end()) +erase(end() - 1) +pop_back() +resize(n, ...) where n < size() +pop_front() with size() == 1 + +
[ +Post Kona, Steve LoBasso notes: +]
+ + ++My only issue with the proposed resolution is that it might not be clear +that pop_front() [where size() == 1] can invalidate past-the-end +iterators. ++ + + +
Proposed resolution:
++Change 23.2.2.3 [deque.modifiers], p4: +
+ +++ + + +iterator erase(const_iterator position); +iterator erase(const_iterator first, const_iterator last); ++ ++++-4- Effects: An erase in the middle of the deque +invalidates all the iterators and references to elements of the +deque and the past-the-end iterator. An erase at +either end of the deque invalidates only the iterators and the +references to the erased elements, except that erasing at the end +also invalidates the past-the-end iterator. +
+
[ +Kona (2007): Proposed wording added and moved to Review. +]
+ + +[ +Bellevue: +]
+ + ++Note that there is existing code that relies on iterators not being +invalidated, but there are also existing implementations that do +invalidate iterators. Thus, such code is not portable in any case. There +is a pop_front() note, which should possibly be a separate issue. Mike +Spertus to evaluate and, if need be, file an issue. ++ + + + +
Section: 27.6.2.6.2 [ostream.inserters.arithmetic] Status: WP + Submitter: Daniel Krügler Date: 2007-02-17
+View all other issues in [ostream.inserters.arithmetic].
+View all issues with WP status.
+Discussion:
++The arithmetic inserters are described in 27.6.2.6.2 [ostream.inserters.arithmetic]. +Although the section starts with a listing of the inserters including +the new ones: +
+ ++ +operator<<(long long val ); +operator<<(unsigned long long val ); +
+the text in paragraph 1, which describes the corresponding effects +of the inserters, depending on the actual type of val, does not +handle the types long long and unsigned long long. +
+ +[ +Alisdair: In addition to the (unsigned) long long problem, that whole paragraph +misses any reference to extended integral types supplied by the +implementation - one of the additions by core a couple of working papers +back. +]
+ + + + +Proposed resolution:
++In 27.6.2.6.2 [ostream.inserters.arithmetic]/1 change the third sentence +
+ ++When val is of type bool, long, unsigned +long, long long, unsigned long long, double, +long double, or const void*, the formatting conversion +occurs as if it performed the following code fragment: ++ + + + + +
Section: 27.8.1.1 [filebuf], 22.2.2.2.2 [facet.num.put.virtuals] Status: WP + Submitter: Daniel Krügler Date: 2007-02-20
+View all issues with WP status.
+Discussion:
++The current standard 14882:2003(E) as well as N2134 have the +following +defects: +
+ ++27.8.1.1 [filebuf]/5 says: +
+ +++ ++In order to support file I/O and multibyte/wide character conversion, conversions are performed using members of a +facet, referred to as a_codecvt in following sections, obtained "as if" by +
++codecvt<charT,char,typename traits::state_type> a_codecvt = + use_facet<codecvt<charT,char,typename traits::state_type> >(getloc()); +
+use_facet returns a const facet reference and no facet is +copyconstructible, so the codecvt construction should fail to compile. +
+ ++A similar issue arises in 22.2.2.2.2 [facet.num.put.virtuals]/15 for num_punct. +
+ + +Proposed resolution:
++In 27.8.1.1 [filebuf]/5 change the "as if" code +
+ ++ +const codecvt<charT,char,typename traits::state_type>& a_codecvt = + use_facet<codecvt<charT,char,typename traits::state_type> >(getloc()); +
+In 22.2.2.2.2 [facet.num.put.virtuals]/15 (This is para 5 in N2134) change +
+ +++ ++A local variable punct is initialized via +
++const numpunct<charT>& punct = use_facet< numpunct<charT> >(str.getloc() ); +
+(Please note also the additional provided trailing semicolon) +
+ + + + + + +Section: 28.10.4 [re.results.form] Status: WP + Submitter: Daniel Krügler Date: 2007-02-26
+View all issues with WP status.
+Discussion:
++28.10.4 [re.results.form] (root and para 3) in N2134 defines the two function template +members format as non-const functions, although they are declared +as const in 28.10 [re.results]/3. +
+ + +Proposed resolution:
++Add the missing const specifier to both format overloads described +in section 28.10.4 [re.results.form]. +
+ + + + + +Section: 28.12.2 [re.tokiter] Status: WP + Submitter: Daniel Krügler Date: 2007-03-05
+View all other issues in [re.tokiter].
+View all issues with WP status.
+Discussion:
++Both the class definition of regex_token_iterator (28.12.2 +[re.tokiter]/6) and the latter member specifications (28.12.2.2 +[re.tokiter.comp]/1+2) declare both comparison operators as +non-const functions. Furtheron, both dereference operators are +unexpectedly also declared as non-const in 28.12.2 [re.tokiter]/6 +as well as in (28.12.2.3 [re.tokiter.deref]/1+2). +
+ + +Proposed resolution:
++1) In (28.12.2 [re.tokiter]/6) change the current declarations +
+ ++ +bool operator==(const regex_token_iterator&) const; +bool operator!=(const regex_token_iterator&) const; +const value_type& operator*() const; +const value_type* operator->() const; +
+2) In 28.12.2.2 [re.tokiter.comp] change the following declarations +
+ ++ +bool operator==(const regex_token_iterator& right) const; +bool operator!=(const regex_token_iterator& right) const; +
+3) In 28.12.2.3 [re.tokiter.deref] change the following declarations +
+ ++ + +const value_type& operator*() const; +const value_type* operator->() const; +
[ +Kona (2007): The LWG adopted the proposed resolution of N2409 for this issue (which +is to adopt the proposed wording in this issue). +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 28.12.2.1 [re.tokiter.cnstr] Status: WP + Submitter: Daniel Krügler Date: 2007-03-05
+View all other issues in [re.tokiter.cnstr].
+View all issues with WP status.
+Discussion:
++The text provided in 28.12.2.1 [re.tokiter.cnstr]/2+3 describes +the effects of the three non-default constructors of class +template regex_token_iterator but is does not clarify which values +are legal values for submatch/submatches. This becomes +an issue, if one takes 28.12.2 [re.tokiter]/9 into account, which explains +the notion of a "current match" by saying: +
+ ++ ++The current match is (*position).prefix() if subs[N] +== -1, or (*position)[subs[N]] for any other value of +subs[N]. +
+It's not clear to me, whether other negative values except -1 +are legal arguments or not - it seems they are not. +
+ + +Proposed resolution:
++Add the following precondition paragraph just before the current +28.12.2.1 [re.tokiter.cnstr]/2: +
+ ++ + ++Requires: Each of the initialization values of subs must be >= -1. +
[ +Kona (2007): The LWG adopted the proposed resolution of N2409 for this issue (which +is to adopt the proposed wording in this issue). +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 28.12.1 [re.regiter] Status: WP + Submitter: Daniel Krügler Date: 2007-03-05
+View all issues with WP status.
+Discussion:
+Both the class definition of regex_iterator (28.12.1 [re.regiter]/1) +and the latter member specification (28.12.1.2 [re.regiter.comp]/1+2) +declare both comparison operators as +non-const functions. Furtheron, both dereference operators are +unexpectedly also declared as non-const in 28.12.1 [re.regiter]/1 +as well as in (28.12.1.3 [re.regiter.deref]/1+2). +
+ + +Proposed resolution:
++1) In (28.12.1 [re.regiter]/1) change the current declarations +
+ ++ +bool operator==(const regex_iterator&) const; +bool operator!=(const regex_iterator&) const; +const value_type& operator*() const; +const value_type* operator->() const; +
+2) In 28.12.1.3 [re.regiter.deref] change the following declarations +
+ ++ +const value_type& operator*() const; +const value_type* operator->() const; +
+3) In 28.12.1.2 [re.regiter.comp] change the following declarations +
+ ++ + +bool operator==(const regex_iterator& right) const; +bool operator!=(const regex_iterator& right) const; +
[ +Kona (2007): The LWG adopted the proposed resolution of N2409 for this issue (which +is to adopt the proposed wording in this issue). +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 26.4.1.3 [rand.req.eng] Status: WP + Submitter: Daniel Krügler Date: 2007-03-08
+View all other issues in [rand.req.eng].
+View all issues with WP status.
+Discussion:
++Table 98 and para 5 in 26.4.1.3 [rand.req.eng] specify +the IO insertion and extraction semantic of random +number engines. It can be shown, v.i., that the specification +of the extractor cannot guarantee to fulfill the requirement +from para 5: +
+ ++ ++If a textual representation written via os << x was +subsequently read via is >> v, then x == v provided that +there have been no intervening invocations of x or of v. +
+The problem is, that the extraction process described in +table 98 misses to specify that it will initially set the +if.fmtflags to ios_base::dec, see table 104: +
+ ++ ++dec: converts integer input or generates integer output +in decimal base +
+Proof: The following small program demonstrates the violation +of requirements (exception safety not fulfilled): +
+ ++ +#include <cassert> +#include <ostream> +#include <iostream> +#include <iomanip> +#include <sstream> + +class RanNumEngine { + int state; +public: + RanNumEngine() : state(42) {} + + bool operator==(RanNumEngine other) const { + return state == other.state; + } + + template <typename Ch, typename Tr> + friend std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& os, RanNumEngine engine) { + Ch old = os.fill(os.widen(' ')); // Sets space character + std::ios_base::fmtflags f = os.flags(); + os << std::dec << std::left << engine.state; // Adds ios_base::dec|ios_base::left + os.fill(old); // Undo + os.flags(f); + return os; + } + + template <typename Ch, typename Tr> + friend std::basic_istream<Ch, Tr>& operator>>(std::basic_istream<Ch, Tr>& is, RanNumEngine& engine) { + // Uncomment only for the fix. + + //std::ios_base::fmtflags f = is.flags(); + //is >> std::dec; + is >> engine.state; + //is.flags(f); + return is; + } +}; + +int main() { + std::stringstream s; + s << std::setfill('#'); // No problem + s << std::oct; // Yikes! + // Here starts para 5 requirements: + RanNumEngine x; + s << x; + RanNumEngine v; + s >> v; + assert(x == v); // Fails: 42 == 34 +} +
+A second, minor issue seems to be, that the insertion +description from table 98 unnecessarily requires the +addition of ios_base::fixed (which only influences floating-point +numbers). Its not entirely clear to me whether the proposed +standard does require that the state of random number engines +is stored in integral types or not, but I have the impression +that this is the indent, see e.g. p. 3 +
+ ++ ++The specification of each random number engine defines the +size of its state in multiples of the size of its result_type. +
+If other types than integrals are supported, then I wonder why +no requirements are specified for the precision of the stream. +
+ ++See N2391 and +N2423 +for some further discussion. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2423. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 26.4.7.2 [rand.util.canonical] Status: WP + Submitter: Daniel Krügler Date: 2007-03-08
+View all other issues in [rand.util.canonical].
+View all issues with WP status.
+Discussion:
++In 26.4.2 [rand.synopsis] we have the declaration +
+ ++ +template<class RealType, class UniformRandomNumberGenerator, + size_t bits> +result_type generate_canonical(UniformRandomNumberGenerator& g); +
+Besides the "result_type" issue (already recognized by Bo Persson +at Sun, 11 Feb 2007 05:26:47 GMT in this group) it's clear, that +the template parameter order is not reasonably choosen: Obviously +one always needs to specify all three parameters, although usually +only two are required, namely the result type RealType and the +wanted bits, because UniformRandomNumberGenerator can usually +be deduced. +
+ ++See N2391 and +N2423 +for some further discussion. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2423. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 20.6 [function.objects] Status: WP + Submitter: Beman Dawes Date: 2007-04-02
+View all other issues in [function.objects].
+View all issues with WP status.
+Discussion:
+Section 20.6 [function.objects] provides function +objects for some unary and binary +operations, but others are missing. In a LWG reflector discussion, beginning +with c++std-lib-18078, pros and cons of adding some of the missing operations +were discussed. Bjarne Stroustrup commented "Why standardize what isn't used? +Yes, I see the chicken and egg problems here, but it would be nice to see a +couple of genuine uses before making additions."
+A number of libraries, including Rogue Wave, GNU, Adobe ASL, and Boost, have +already added these functions, either publicly or for internal use. For example, +Doug Gregor commented: "Boost will also add ... (|, &, ^) in 1.35.0, because we +need those function +objects to represent various parallel +collective operations (reductions, prefix reductions, etc.) in the new Message +Passing Interface (MPI) library."
+Because the bitwise operators have the strongest use cases, the proposed +resolution is limited to them.
+ + +Proposed resolution:
+To 20.6 [function.objects], Function objects, paragraph 2, add to the header +<functional> synopsis:
+++template <class T> struct bit_and; +template <class T> struct bit_or; +template <class T> struct bit_xor;+
At a location in clause 20 to be determined by the Project Editor, add:
+++ + + + + +The library provides basic function object classes for all of the bitwise + operators in the language ([expr.bit.and], [expr.or], [exp.xor]).
+template <class T> struct bit_and : binary_function<T,T,T> { + T operator()(const T& x , const T& y ) const; +};++++
operator()
returnsx & y
.template <class T> struct bit_or : binary_function<T,T,T> { + T operator()(const T& x , const T& y ) const; +};++++
operator()
returnsx | y
.template <class T> struct bit_xor : binary_function<T,T,T> { + T operator()(const T& x , const T& y ) const; +};++++
operator()
returnsx ^ y
.
Section: 27.6.1.2.2 [istream.formatted.arithmetic] Status: WP + Submitter: Daniel Krügler Date: 2007-04-01
+View all other issues in [istream.formatted.arithmetic].
+View all issues with WP status.
+Discussion:
++To the more drastic changes of 27.6.1.2.2 [istream.formatted.arithmetic] in the current draft N2134 belong +the explicit description of the extraction of the types short and int in +terms of as-if code fragments. +
+ +Proposed resolution:
++In 27.6.1.2.2 [istream.formatted.arithmetic]/2 change the current as-if code fragment +
++ +typedef num_get<charT,istreambuf_iterator<charT,traits> > numget; +iostate err = 0; +long lval; +use_facet<numget>(loc).get(*this, 0, *this, err, lval ); +if (err == 0) { +&&if (lval < numeric_limits<short>::min() || numeric_limits<short>::max() < lval))+ err = ios_base::failbit; + else + val = static_cast<short>(lval); +} +setstate(err); +
+Similarily in 27.6.1.2.2 [istream.formatted.arithmetic]/3 change the current as-if fragment +
+ ++typedef num_get<charT,istreambuf_iterator<charT,traits> > numget; +iostate err = 0; +long lval; +use_facet<numget>(loc).get(*this, 0, *this, err, lval ); +if (err == 0) { +&&if (lval < numeric_limits<int>::min() || numeric_limits<int>::max() < lval))+ err = ios_base::failbit; + else + val = static_cast<int>(lval); +} +setstate(err); +
[ +Kona (2007): Note to the editor: the name lval in the call to use_facet +is incorrectly italicized in the code fragments corresponding to +operator>>(short &) and operator >>(int &). Also, val -- which appears +twice on the line with the static_cast in the proposed resolution -- +should be italicized. Also, in response to part two of the issue: this +is deliberate. +]
+ + + + + +Section: 22.2.1.4.2 [locale.codecvt.virtuals] Status: WP + Submitter: Thomas Plum Date: 2007-04-16
+View all other issues in [locale.codecvt.virtuals].
+View all issues with WP status.
+Discussion:
++22.2.1.4.2 [locale.codecvt.virtuals], para 7 says (regarding do_unshift): +
+ ++ ++Effects: Places characters starting at to that should be appended to +terminate a sequence when the current stateT is given by +state.237) Stores no more than (to_limit - +to) destination elements, and leaves the to_next +pointer pointing one beyond the last element successfully stored. +codecvt<char, char, mbstate_t> stores no characters. +
+The following objection has been raised: +
+ ++ ++Since the C++ Standard permits a nontrivial conversion for the required +instantiations of codecvt, it is overly restrictive to say that +do_unshift must store no characters and return noconv. +
+[Plum ref _222152Y50] +
+ + +Proposed resolution:
++Change 22.2.1.4.2 [locale.codecvt.virtuals], p7: +
+ +++ + + + + ++Effects: Places characters starting at to that should be +appended to terminate a sequence when the current stateT is +given by state.237) Stores no more than (to_limit -to) +destination elements, and leaves the to_next pointer pointing one +beyond the last element successfully stored.
+codecvt<char, char, +mbstate_t> stores no characters.+
Section: 22.2.1.4.2 [locale.codecvt.virtuals] Status: WP + Submitter: Thomas Plum Date: 2007-04-16
+View all other issues in [locale.codecvt.virtuals].
+View all issues with WP status.
+Discussion:
++22.2.1.4.2 [locale.codecvt.virtuals], para 8 says: +
+ ++ ++codecvt<char,char,mbstate_t>, returns noconv. +
+The following objection has been raised: +
+ ++ ++Despite what the C++ Standard +says, unshift can't always return noconv for the default facets, since +they can be nontrivial. At least one implementation does whatever the +C functions do. +
+[Plum ref _222152Y62] +
+ + +Proposed resolution:
++Change 22.2.1.4.2 [locale.codecvt.virtuals], p8: +
+ +++ + + + + + +Returns: An enumeration value, as summarized in Table 76:
+...
++
+codecvt<char,char,mbstate_t>, returns noconv.+
Section: 22.2.6.3.2 [locale.moneypunct.virtuals] Status: WP + Submitter: Thomas Plum Date: 2007-04-16
+View all other issues in [locale.moneypunct.virtuals].
+View all issues with WP status.
+Discussion:
++22.2.6.3.2 [locale.moneypunct.virtuals], para 4 footnote 257 says +
+ ++ ++257) For international +specializations (second template parameter true) this is always four +characters long, usually three letters and a space. +
+The following objection has been raised: +
+ ++ ++The international currency +symbol is whatever the underlying locale says it is, not necessarily +four characters long. +
+[Plum ref _222632Y41] +
+ + +Proposed resolution:
++Change footnote 253 in 22.2.6.3.2 [locale.moneypunct.virtuals]: +
+ +++ + + + + ++253) For international specializations (second template +parameter true) this is
+alwaystypically +four characters long, usually three letters and a space. +
Section: 20.1.1 [utility.arg.requirements] Status: WP + Submitter: Howard Hinnant Date: 2007-05-04
+View other active issues in [utility.arg.requirements].
+View all other issues in [utility.arg.requirements].
+View all issues with WP status.
+Discussion:
++The current Swappable is: +
+ +++ ++
+Table 37: Swappable requirements [swappable] ++ expression return type post-condition + swap(s,t) void t has the value originally held by u, and u has the value originally +held by t + + +The Swappable requirement is met by satisfying one or more of the following conditions: +
++
+- +T is Swappable if T satisfies the CopyConstructible requirements (Table 34) +and the CopyAssignable requirements (Table 36); +
+- +T is Swappable if a namespace scope function named swap exists in the same +namespace as the definition of T, such that the expression swap(t,u) is valid +and has the semantics described in this table. +
+
+With the passage of rvalue reference into the language, Swappable needs to be updated to +require only MoveConstructible and MoveAssignable. This is a minimum. +
+ ++Additionally we may want to support proxy references such that the following code is acceptable: +
+ ++ +namespace Mine { + +template <class T> +struct proxy {...}; + +template <class T> +struct proxied_iterator +{ + typedef T value_type; + typedef proxy<T> reference; + reference operator*() const; + ... +}; + +struct A +{ + // heavy type, has an optimized swap, maybe isn't even copyable or movable, just swappable + void swap(A&); + ... +}; + +void swap(A&, A&); +void swap(proxy<A>, A&); +void swap(A&, proxy<A>); +void swap(proxy<A>, proxy<A>); + +} // Mine + +... + +Mine::proxied_iterator<Mine::A> i(...) +Mine::A a; +swap(*i1, a); +
+I.e. here is a call to swap which the user enables swapping between a proxy to a class and the class +itself. We do not need to anything in terms of implementation except not block their way with overly +constrained concepts. That is, the Swappable concept should be expanded to allow swapping +between two different types for the case that one is binding to a user-defined swap. +
+ + + +Proposed resolution:
+ ++Change 20.1.1 [utility.arg.requirements]: +
+ ++ ++ + + ++-1- The template definitions in the C++ Standard Library refer to various +named requirements whose details are set out in tables 31-38. In these +tables, T is a type to be supplied by a C++ program +instantiating a template; a, b, and c are +values of type const T; s and t are modifiable +lvalues of type T; u is a value of type (possibly +const) T; and rv is a non-const +rvalue of type T. +
+ ++
+Table 37: Swappable requirements [swappable] ++ expression return type post-condition + swap(s,t) void +t has the value originally +held by u, and +u has the value originally held +by t + + +The Swappable requirement is met by satisfying one or more of the following conditions: +
++
+- +T is Swappable if T satisfies the +
+CopyConstructibleMoveConstructible +requirements (Table3433) and theCopyAssignableMoveAssignable +requirements (Table3635); +- +T is Swappable if a namespace scope function named +swap exists in the same namespace as the definition of +T, such that the expression +swap(t,u) is valid and has the +semantics described in this table. +
+
[ +Kona (2007): We like the change to the Swappable requirements to use +move semantics. The issue relating to the support of proxies is +separable from the one relating to move semantics, and it's bigger than +just swap. We'd like to address only the move semantics changes under +this issue, and open a separated issue (742) to handle proxies. Also, there +may be a third issue, in that the current definition of Swappable does +not permit rvalues to be operands to a swap operation, and Howard's +proposed resolution would allow the right-most operand to be an rvalue, +but it would not allow the left-most operand to be an rvalue (some swap +functions in the library have been overloaded to permit left operands to +swap to be rvalues). +]
+ + + + + +Section: 20.7.11 [unique.ptr] Status: WP + Submitter: Howard Hinnant Date: 2007-05-04
+View all other issues in [unique.ptr].
+View all issues with WP status.
+Discussion:
++Since the publication of +N1856 +there have been a few small but significant advances which should be included into +unique_ptr. There exists a +example implmenation +for all of these changes. +
+ ++Even though unique_ptr<void> is not a valid use case (unlike for shared_ptr<void>), +unexpected cases to crop up which require the instantiation of the interface of unique_ptr<void> +even if it is never used. For example see +LWG 541 for how this accidently +happened to auto_ptr. I believe the most robust way to protect unique_ptr against this +type of failure is to augment the return type of unique_ptr<T>:operator*() with +add_lvalue_reference<T>::type. This means that given an instantiated unique_ptr<void> +the act of dereferencing it will simply return void instead of causing a compile time failure. +This is simpler than creating a unique_ptr<void> specialization which isn't robust in the +face of cv-qualified void types. +
+ ++This resolution also supports instantiations such as unique_ptr<void, free_deleter> +which could be very useful to the client. +
+ ++Efforts have been made to better support containers and smart pointers in shared +memory contexts. One of the key hurdles in such support is not assuming that a +pointer type is actually a T*. This can easily be accomplished +for unique_ptr by having the deleter define the pointer type: +D::pointer. Furthermore this type can easily be defaulted to +T* should the deleter D choose not to define a pointer +type (example implementation +here). +This change has no run time overhead. It has no interface overhead on +authors of custom delter types. It simply allows (but not requires) +authors of custom deleter types to define a smart pointer for the +storage type of unique_ptr if they find such functionality +useful. std::default_delete is an example of a deleter which +defaults pointer to T* by simply ignoring this issue +and not including a pointer typedef. +
++When the deleter type is a function pointer then it is unsafe to construct +a unique_ptr without specifying the function pointer in the constructor. +This case is easy to check for with a static_assert assuring that the +deleter is not a pointer type in those constructors which do not accept deleters. +
+ ++ +unique_ptr<A, void(*)(void*)> p(new A); // error, no function given to delete the pointer! +
[ +Kona (2007): We don't like the solution given to the first bullet in +light of concepts. The second bullet solves the problem of supporting +fancy pointers for one library component only. The full LWG needs to +decide whether to solve the problem of supporting fancy pointers +piecemeal, or whether a paper addressing the whole library is needed. We +think that the third bullet is correct. +]
+ + +[ +Post Kona: Howard adds example user code related to the first bullet: +]
+ + +++ +void legacy_code(void*, std::size_t); + +void foo(std::size_t N) +{ + std::unique_ptr<void, void(*)(void*)> ptr(std::malloc(N), std::free); + legacy_code(ptr.get(), N); +} // unique_ptr used for exception safety purposes ++
+I.e. unique_ptr<void> is a useful tool that we don't want +to disable with concepts. The only part of unique_ptr<void> we +want to disable (with concepts or by other means) are the two member functions: +
+ ++ + + +T& operator*() const; +T* operator->() const; +
Proposed resolution:
+ +[ +I am grateful for the generous aid of Peter Dimov and Ion Gaztañaga in helping formulate and review +the proposed resolutions below. +]
+ + ++Change 20.7.11.2 [unique.ptr.single]: +
+ ++ +template <class T, class D = default_delete<T>> class unique_ptr { + ... +T&typename add_lvalue_reference<T>::type operator*() const; + ... +}; +
+Change 20.7.11.2.4 [unique.ptr.single.observers]: +
+ ++ +T&typename add_lvalue_reference<T>::type operator*() const; +
+Change 20.7.11.2 [unique.ptr.single]: +
+ ++ +template <class T, class D = default_delete<T>> class unique_ptr { +public: + typedef implementation (see description below) pointer; + ... + explicit unique_ptr(T*pointer p); + ... + unique_ptr(T*pointer p, implementation defined (see description below) d); + unique_ptr(T*pointer p, implementation defined (see description below) d); + ... +T*pointer operator->() const; +T*pointer get() const; + ... +T*pointer release(); + void reset(T*pointer p =0pointer()); +}; +
+ +-3- If the type remove_reference<D>::type::pointer +exists, then unique_ptr<T, D>::pointer is a typedef to +remove_reference<D>::type::pointer. Otherwise +unique_ptr<T, D>::pointer is a typedef to T*. +The type unique_ptr<T, D>::pointer shall be CopyConstructible +and CopyAssignable. + +
+ ++Change 20.7.11.2.1 [unique.ptr.single.ctor]: +
+ ++ +unique_ptr(T*pointer p); +... +unique_ptr(T*pointer p, implementation defined d); +unique_ptr(T*pointer p, implementation defined d); +... +unique_ptr(T*pointer p, const A& d); +unique_ptr(T*pointer p, A&& d); +... +unique_ptr(T*pointer p, A& d); +unique_ptr(T*pointer p, A&& d); +... +unique_ptr(T*pointer p, const A& d); +unique_ptr(T*pointer p, const A&& d); +... +
+-23- Requires: If D is not a reference type,
+construction of the deleter D from an rvalue of type E
+must shall be well formed and not throw an exception. If D is a
+reference type, then E must shall be the same type as D
+(diagnostic required). U* unique_ptr<U,E>::pointer
+must shall be implicitly convertible to T*
+pointer.
+
+-25- Postconditions: get() == value u.get() had before
+the construction, modulo any required offset adjustments resulting from
+the cast from U*
+unique_ptr<U,E>::pointer to T*
+pointer. get_deleter() returns a reference to the
+internally stored deleter which was constructed from
+u.get_deleter().
+
+Change 20.7.11.2.3 [unique.ptr.single.asgn]: +
+ +++ ++-8- Requires: Assignment of the deleter D from an rvalue +D
+mustshall not throw an exception.U*+unique_ptr<U,E>::pointermustshall be implicitly +convertible toT*pointer. +
+Change 20.7.11.2.4 [unique.ptr.single.observers]: +
+ +++ ++... +T*pointer operator->() const;+T*pointer get() const;
+Change 20.7.11.2.5 [unique.ptr.single.modifiers]: +
+ +++ ++... +T*pointer release();void reset(+T*pointer p =0pointer());
+Change 20.7.11.3 [unique.ptr.runtime]: +
+ ++ +template <class T, class D> class unique_ptr<T[], D> { +public: + typedef implementation pointer; + ... + explicit unique_ptr(T*pointer p); + ... + unique_ptr(T*pointer p, implementation defined d); + unique_ptr(T*pointer p, implementation defined d); + ... +T*pointer get() const; + ... +T*pointer release(); + void reset(T*pointer p =0pointer()); +}; +
+Change 20.7.11.3.1 [unique.ptr.runtime.ctor]: +
+ +++ +unique_ptr(+ +T*pointer p); +unique_ptr(T*pointer p, implementation defined d); +unique_ptr(T*pointer p, implementation defined d); ++These constructors behave the same as in the primary template except +that they do not accept pointer types which are convertible to +
+T*pointer. [Note: One +implementation technique is to create private templated overloads of +these members. -- end note] +
+Change 20.7.11.3.3 [unique.ptr.runtime.modifiers]: +
+ +++ +void reset(+ +T*pointer p =0pointer()); ++-1- Requires: Does not accept pointer types which are convertible +to
+T*pointer (diagnostic +required). [Note: One implementation technique is to create a private +templated overload. -- end note] +
+Change 20.7.11.2.1 [unique.ptr.single.ctor]: +
+ +++ +unique_ptr();++++Requires: D
+mustshall be default constructible, and that +constructionmustshall not throw an exception. Dmustshall not be a +reference type or pointer type (diagnostic required). +unique_ptr(+T*pointer p);+++Requires: The expression D()(p)
+mustshall be well formed. +The default constructor of Dmustshall not throw an exception. +Dmustshall not be a reference type or pointer type (diagnostic +required). +
Section: 20.7.12.2 [util.smartptr.shared] Status: WP + Submitter: Peter Dimov Date: 2007-05-05
+View other active issues in [util.smartptr.shared].
+View all other issues in [util.smartptr.shared].
+View all issues with WP status.
+Discussion:
++N1856 does not propose +any changes to shared_ptr. It needs to be updated to use a rvalue reference where appropriate +and to interoperate with unique_ptr as it does with auto_ptr. +
+ + +Proposed resolution:
+ ++Change 20.7.12.2 [util.smartptr.shared] as follows: +
+ +++ +template<class Y> explicit shared_ptr(auto_ptr<Y>+&&& r); +template<class Y, class D> explicit shared_ptr(const unique_ptr<Y,D>& r) = delete; +template<class Y, class D> explicit shared_ptr(unique_ptr<Y,D>&& r); +... +template<class Y> shared_ptr& operator=(auto_ptr<Y>&&& r); +template<class Y, class D> shared_ptr& operator=(const unique_ptr<Y,D>& r) = delete; +template<class Y, class D> shared_ptr& operator=(unique_ptr<Y,D>&& r);
+Change 20.7.12.2.1 [util.smartptr.shared.const] as follows: +
+ +++ +template<class Y> shared_ptr(auto_ptr<Y>+&&& r);
+Add to 20.7.12.2.1 [util.smartptr.shared.const]: +
+ +++ +template<class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);++ ++ ++Effects: Equivalent to shared_ptr( r.release(), r.get_deleter() ) when D is + not a reference type, shared_ptr( r.release(), ref( r.get_deleter() ) ) + otherwise. +
+ ++Exception safety: If an exception is thrown, the constructor has no effect. +
+
+Change 20.7.12.2.3 [util.smartptr.shared.assign] as follows: +
+ +++ +template<class Y> shared_ptr& operator=(auto_ptr<Y>+&&& r);
+Add to 20.7.12.2.3 [util.smartptr.shared.assign]: +
+ +++ + + +template<class Y, class D> shared_ptr& operator=(unique_ptr<Y,D>&& r);+ +++ ++-4- Effects: Equivalent to shared_ptr(std::move(r)).swap(*this). +
++-5- Returns: *this. +
+
[ +Kona (2007): We may need to open an issue (743) to deal with the question of +whether shared_ptr needs an rvalue swap. +]
+ + + + + +Section: 26.4.7.1 [rand.util.seedseq] Status: WP + Submitter: Charles Karney Date: 2007-05-15
+View other active issues in [rand.util.seedseq].
+View all other issues in [rand.util.seedseq].
+View all issues with WP status.
+Discussion:
++seed_seq::randomize provides a mechanism for initializing random number +engines which ideally would yield "distant" states when given "close" +seeds. The algorithm for seed_seq::randomize given in the current +Working Draft for C++, +N2284 +(2007-05-08), has 3 weaknesses +
+ +Collisions in state. Because of the way the state is initialized, + seeds of different lengths may result in the same state. The + current version of seed_seq has the following properties:
++ The proposed algorithm (below) has the considerably stronger + properties:
+Poor mixing of v's entropy into the state. Consider v.size() == n + and hold v[n/2] thru v[n-1] fixed while varying v[0] thru v[n/2-1], + a total of 2^(16n) possibilities. Because of the simple recursion + used in seed_seq, begin[n/2] thru begin[n-1] can take on only 2^64 + possible states.
+ +The proposed algorithm uses a more complex recursion which results + in much better mixing.
++The current algorithm for seed_seq::randomize is adapted by me from the +initialization procedure for the Mersenne Twister by Makoto Matsumoto +and Takuji Nishimura. The weakness (2) given above was communicated to +me by Matsumoto last year. +
++The proposed replacement for seed_seq::randomize is due to Mutsuo Saito, +a student of Matsumoto, and is given in the implementation of the +SIMD-oriented Fast Mersenne Twister random number generator SFMT. +http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html +http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/SFMT-src-1.2.tar.gz +
++See +Mutsuo Saito, +An Application of Finite Field: Design and Implementation of 128-bit +Instruction-Based Fast Pseudorandom Number Generator, +Master's Thesis, Dept. of Math., Hiroshima University (Feb. 2007) +http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/M062821.pdf +
++One change has been made here, namely to treat the case of small n +(setting t = (n-1)/2 for n < 7). +
++Since seed_seq was introduced relatively recently there is little cost +in making this incompatible improvement to it. +
+ ++See N2391 and +N2423 +for some further discussion. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2423. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 26.4.1.3 [rand.req.eng] Status: WP + Submitter: Charles Karney Date: 2007-05-15
+View all other issues in [rand.req.eng].
+View all issues with WP status.
+Discussion:
++Section 26.4.1.3 [rand.req.eng] Random number engine requirements: +
+ ++This change follows naturally from the proposed change to +seed_seq::randomize in 677. +
+ ++In table 104 the description of X(q) contains a special treatment of +the case q.size() == 0. This is undesirable for 4 reasons: +
+ ++See N2391 and +N2423 +for some further discussion. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2423. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 23.2 [sequences] Status: WP + Submitter: Howard Hinnant Date: 2007-06-11
+View all issues with WP status.
+Discussion:
++The C++98 standard specifies that one member function alone of the containers +passes its parameter (T) by value instead of by const reference: +
+ ++ +void resize(size_type sz, T c = T()); +
+This fact has been discussed / debated repeatedly over the years, the first time +being even before C++98 was ratified. The rationale for passing this parameter by +value has been: +
+ +++ ++So that self referencing statements are guaranteed to work, for example: +
++v.resize(v.size() + 1, v[0]); +
+However this rationale is not convincing as the signature for push_back is: +
+ ++ +void push_back(const T& x); +
+And push_back has similar semantics to resize (append). +And push_back must also work in the self referencing case: +
+ ++ +v.push_back(v[0]); // must work +
+The problem with passing T by value is that it can be significantly more +expensive than passing by reference. The converse is also true, however when it is +true it is usually far less dramatic (e.g. for scalar types). +
+ ++Even with move semantics available, passing this parameter by value can be expensive. +Consider for example vector<vector<int>>: +
+ ++ +std::vector<int> x(1000); +std::vector<std::vector<int>> v; +... +v.resize(v.size()+1, x); +
+In the pass-by-value case, x is copied once to the parameter of +resize. And then internally, since the code can not know at compile +time by how much resize is growing the vector, x is +usually copied (not moved) a second time from resize's parameter into its proper place +within the vector. +
+ ++With pass-by-const-reference, the x in the above example need be copied +only once. In this case, x has an expensive copy constructor and so any +copies that can be saved represents a significant savings. +
+ ++If we can be efficient for push_back, we should be efficient for resize +as well. The resize taking a reference parameter has been coded and shipped in the +CodeWarrior library with no reports of problems which I am aware of. +
+ + + +Proposed resolution:
++Change 23.2.2 [deque], p2: +
+ ++ +class deque { + ... + void resize(size_type sz, const T& c); +
+Change 23.2.2.2 [deque.capacity], p3: +
+ ++ +void resize(size_type sz, const T& c); +
+Change 23.2.4 [list], p2: +
+ ++ +class list { + ... + void resize(size_type sz, const T& c); +
+Change 23.2.4.2 [list.capacity], p3: +
+ ++ +void resize(size_type sz, const T& c); +
+Change 23.2.6 [vector], p2: +
+ ++ +class vector { + ... + void resize(size_type sz, const T& c); +
+Change 23.2.6.2 [vector.capacity], p11: +
+ ++ + + + + + +void resize(size_type sz, const T& c); +
Section: 24.4.3.1 [move.iterator] Status: WP + Submitter: Howard Hinnant Date: 2007-06-11
+View all issues with WP status.
+Discussion:
++move_iterator's operator-> return type pointer +does not consistently match the type which is returned in the description +in 24.4.3.3.5 [move.iter.op.ref]. +
+ ++ + +template <class Iterator> +class move_iterator { +public: + ... + typedef typename iterator_traits<Iterator>::pointer pointer; + ... + pointer operator->() const {return current;} + ... +private: + Iterator current; // exposition only +}; +
+There are two possible fixes. +
+ ++The first solution is the one chosen by reverse_iterator. A potential +disadvantage of this is it may not work well with iterators which return a +proxy on dereference and that proxy has overloaded operator&(). Proxy +references often need to overloaad operator&() to return a proxy +pointer. That proxy pointer may or may not be the same type as the iterator's +pointer type. +
+ ++By simply returning the Iterator and taking advantage of the fact that +the language forwards calls to operator-> automatically until it +finds a non-class type, the second solution avoids the issue of an overloaded +operator&() entirely. +
+ +Proposed resolution:
++Change the synopsis in 24.4.3.1 [move.iterator]: +
+ ++ + + + + + +typedeftypename iterator_traits<Iterator>::pointerpointer; +
Section: 28.9.2 [re.submatch.op] Status: WP + Submitter: Nozomu Katoo Date: 2007-05-27
+View all issues with WP status.
+Discussion:
++In 28.9.2 [re.submatch.op] of N2284, +operator functions numbered 31-42 seem impossible to compare. E.g.: +
+ +++ +template <class BiIter> + bool operator==(typename iterator_traits<BiIter>::value_type const& lhs, + const sub_match<BiIter>& rhs); +++++-31- Returns: lhs == rhs.str(). +
+
+When char* is used as BiIter, iterator_traits<BiIter>::value_type would be +char, so that lhs == rhs.str() ends up comparing a char value and an object +of std::basic_string<char>. However, the behaviour of comparison between +these two types is not defined in 21.3.8 [string.nonmembers] of N2284. + This applies when wchar_t* is used as BiIter. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2409. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2409 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 28.8.2 [re.regex.construct] Status: WP + Submitter: Eric Niebler Date: 2007-06-03
+View all issues with WP status.
+Discussion:
++Looking at N2284, 28.8 [re.regex], p3 basic_regex class template synopsis shows this +constructor: +
++ +template <class InputIterator> + basic_regex(InputIterator first, InputIterator last, + flag_type f = regex_constants::ECMAScript); +
+In 28.8.2 [re.regex.construct], p15, the constructor appears with this signature: +
+ ++ +template <class ForwardIterator> + basic_regex(ForwardIterator first, ForwardIterator last, + flag_type f = regex_constants::ECMAScript); +
+ForwardIterator is probably correct, so the synopsis is wrong. +
+ +[ +John adds: +]
+ + +++ + ++I think either could be implemented? Although an input iterator would +probably require an internal copy of the string being made. +
++I have no strong feelings either way, although I think my original intent +was InputIterator. +
+
Proposed resolution:
++Adopt the proposed resolution in +N2409. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2409 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 24.4.1.3.19 [reverse.iter.opdiff], 24.4.3.3.14 [move.iter.nonmember] Status: WP + Submitter: Bo Persson Date: 2007-06-10
+View all issues with WP status.
+Discussion:
++In C++03 the difference between two reverse_iterators +
++ri1 - ri2 +
+is possible to compute only if both iterators have the same base +iterator. The result type is the difference_type of the base iterator. +
++In the current draft, the operator is defined as 24.4.1.3.19 [reverse.iter.opdiff] +
++template<class Iterator1, class Iterator2> +typename reverse_iterator<Iterator>::difference_type + operator-(const reverse_iterator<Iterator1>& x, + const reverse_iterator<Iterator2>& y); +
+The return type is the same as the C++03 one, based on the no longer +present Iterator template parameter. +
++Besides being slightly invalid, should this operator work only when +Iterator1 and Iterator2 has the same difference_type? Or should the +implementation choose one of them? Which one? +
++The same problem now also appears in operator-() for move_iterator +24.4.3.3.14 [move.iter.nonmember]. +
+ + +Proposed resolution:
++Change the synopsis in 24.4.1.1 [reverse.iterator]: +
+ +++ +template <class Iterator1, class Iterator2> ++typename reverse_iterator<Iterator>::difference_typeauto operator-( + const reverse_iterator<Iterator1>& x, + const reverse_iterator<Iterator2>& y) -> decltype(y.current - x.current); +
+Change 24.4.1.3.19 [reverse.iter.opdiff]: +
+ +++ + +template <class Iterator1, class Iterator2> ++typename reverse_iterator<Iterator>::difference_typeauto operator-( + const reverse_iterator<Iterator1>& x, + const reverse_iterator<Iterator2>& y) -> decltype(y.current - x.current); ++++Returns: y.current - x.current. +
+
+Change the synopsis in 24.4.3.1 [move.iterator]: +
+ +++ +template <class Iterator1, class Iterator2> ++typename move_iterator<Iterator>::difference_typeauto operator-( + const move_iterator<Iterator1>& x, + const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base()); +
+Change 24.4.3.3.14 [move.iter.nonmember]: +
+ +++ +template <class Iterator1, class Iterator2> ++typename move_iterator<Iterator>::difference_typeauto operator-( + const move_iterator<Iterator1>& x, + const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base()); ++++Returns: x.base() - y.base(). +
+
[ +Pre Bellevue: This issue needs to wait until the auto -> return language feature +goes in. +]
+ + + + + + + +Section: 20.7.12.2.1 [util.smartptr.shared.const], 20.7.12.3.1 [util.smartptr.weak.const] Status: WP + Submitter: Peter Dimov Date: 2007-05-10
+View all other issues in [util.smartptr.shared.const].
+View all issues with WP status.
+Discussion:
++Since all conversions from shared_ptr<T> to shared_ptr<U> have the same +rank regardless of the relationship between T and U, reasonable user +code that works with raw pointers fails with shared_ptr: +
+ ++ +void f( shared_ptr<void> ); +void f( shared_ptr<int> ); + +int main() +{ + f( shared_ptr<double>() ); // ambiguous +} +
+Now that we officially have enable_if, we can constrain the constructor +and the corresponding assignment operator to only participate in the +overload resolution when the pointer types are compatible. +
+ + +Proposed resolution:
++In 20.7.12.2.1 [util.smartptr.shared.const], change: +
+ ++ ++-14- Requires:
For the second constructorThe +second constructor shall not participate in the overload resolution +unless Y*shall beis implicitly convertible +to T*. +
+In 20.7.12.3.1 [util.smartptr.weak.const], change: +
+ +++ + + + + + ++template<class Y> weak_ptr(shared_ptr<Y> const& r);+weak_ptr(weak_ptr const& r);+template<class Y> weak_ptr(weak_ptr<Y> const& r);+weak_ptr(weak_ptr const& r); +template<class Y> weak_ptr(weak_ptr<Y> const& r); +template<class Y> weak_ptr(shared_ptr<Y> const& r); +++-4- Requires:
FortThe second and +third constructors,shall not participate in the +overload resolution unless Y*shall be+is implicitly convertible to T*. +
Section: 20.6.5.1 [refwrap.const] Status: WP + Submitter: Peter Dimov Date: 2007-05-10
+View all other issues in [refwrap.const].
+View all issues with WP status.
+Discussion:
++The constructor of reference_wrapper is currently explicit. The primary +motivation behind this is the safety problem with respect to rvalues, +which is addressed by the proposed resolution of the previous issue. +Therefore we should consider relaxing the requirements on the +constructor since requests for the implicit conversion keep resurfacing. +
++Also please see the thread starting at c++std-lib-17398 for some good discussion on this subject. +
+ + +Proposed resolution:
++Remove the explicit from the constructor of reference_wrapper. If the +proposed resolution of the previous issue is accepted, remove the +explicit from the T&& constructor as well to keep them in sync. +
+ + + + + +std::bitset::all()
missingSection: 23.3.5 [template.bitset] Status: WP + Submitter: Martin Sebor Date: 2007-06-22
+View all other issues in [template.bitset].
+View all issues with WP status.
+Discussion:
+
+The bitset
class template provides the member function
+any()
to determine whether an object of the type has any
+bits set, and the member function none()
to determine
+whether all of an object's bits are clear. However, the template does
+not provide a corresponding function to discover whether a
+bitset
object has all its bits set. While it is
+possible, even easy, to obtain this information by comparing the
+result of count()
with the result of size()
+for equality (i.e., via b.count() == b.size()
) the
+operation is less efficient than a member function designed
+specifically for that purpose could be. (count()
must
+count all non-zero bits in a bitset
a word at a time
+while all()
could stop counting as soon as it encountered
+the first word with a zero bit).
+
Proposed resolution:
+
+Add a declaration of the new member function all()
to the
+defintion of the bitset
template in 23.3.5 [template.bitset], p1,
+right above the declaration of any()
as shown below:
+
+ +bool operator!=(const bitset<N>& rhs) const; +bool test(size_t pos) const; +bool all() const; +bool any() const; +bool none() const; +
+Add a description of the new member function to the end of 23.3.5.2 [bitset.members] with the following text: +
++ ++
+bool all() const;
++Returns:+count() == size()
. +
+In addition, change the description of any()
and
+none()
for consistency with all()
as
+follows:
+
+ + + + + ++
+bool any() const;
++++Returns:
+true
if any bit in*this
+is onecount() != 0
. ++
+bool none() const;
++++Returns:
+true
if no bit in*this
+is onecount() == 0
. +
std::bitset
and long long
Section: 23.3.5 [template.bitset] Status: WP + Submitter: Martin Sebor Date: 2007-06-22
+View all other issues in [template.bitset].
+View all issues with WP status.
+Discussion:
+
+Objects of the bitset
class template specializations can
+be constructed from and explicitly converted to values of the widest
+C++ integer type, unsigned long
. With the introduction
+of long long
into the language the template should be
+enhanced to make it possible to interoperate with values of this type
+as well, or perhaps uintmax_t
. See c++std-lib-18274 for
+a brief discussion in support of this change.
+
Proposed resolution:
+
+For simplicity, instead of adding overloads for unsigned long
+long
and dealing with possible ambiguities in the spec, replace
+the bitset
ctor that takes an unsigned long
+argument with one taking unsigned long long
in the
+definition of the template as shown below. (The standard permits
+implementations to add overloads on other integer types or employ
+template tricks to achieve the same effect provided they don't cause
+ambiguities or changes in behavior.)
+
++// [bitset.cons] constructors: +bitset(); +bitset(unsigned long long val); +template<class charT, class traits, class Allocator> +explicit bitset( + const basic_string<charT,traits,Allocator>& str, + typename basic_string<charT,traits,Allocator>::size_type pos = 0, + typename basic_string<charT,traits,Allocator>::size_type n = + basic_string<charT,traits,Allocator>::npos); ++
+Make a corresponding change in 23.3.5.1 [bitset.cons], p2: +
+++ ++
+bitset(unsigned long long val);
++Effects: Constructs an object of class bitset<N>, +initializing the first+M
bit positions to the +corresponding bit values inval
. +M
is the smaller ofN
and the +number of bits in the value representation (section [basic.types]) of +unsigned long long
. IfM < +N
istrue
, the remaining bit +positions are initialized to zero. +
+Additionally, introduce a new member function to_ullong()
+to make it possible to convert bitset
to values of the
+new type. Add the following declaration to the definition of the
+template, immediate after the declaration of to_ulong()
+in 23.3.5 [template.bitset], p1, as shown below:
+
++// element access: +bool operator[](size_t pos) const; // for b[i]; +reference operator[](size_t pos); // for b[i]; +unsigned long to_ulong() const; +unsigned long long to_ullong() const; +template <class charT, class traits, class Allocator> +basic_string<charT, traits, Allocator> to_string() const; ++
+And add a description of the new member function to 23.3.5.2 [bitset.members],
+below the description of the existing to_ulong()
(if
+possible), with the following text:
+
++ + + + + ++
+unsigned long long to_ullong() const;
++Throws:+overflow_error
if the integral value +x
corresponding to the bits in*this
+cannot be represented as typeunsigned long long
. ++Returns:+x
. +
Section: 22.2.1.3 [facet.ctype.special] Status: WP + Submitter: Martin Sebor Date: 2007-06-22
+View all issues with WP status.
+Discussion:
+
+The ctype<char>::classic_table()
static member
+function returns a pointer to an array of const
+ctype_base::mask
objects (enums) that contains
+ctype<char>::table_size
elements. The table
+describes the properties of the character set in the "C" locale (i.e.,
+whether a character at an index given by its value is alpha, digit,
+punct, etc.), and is typically used to initialize the
+ctype<char>
facet in the classic "C" locale (the
+protected ctype<char>
member function
+table()
then returns the same value as
+classic_table()
).
+
+However, while ctype<char>::table_size
(the size of
+the table) is a public static const member of the
+ctype<char>
specialization, the
+classic_table()
static member function is protected. That
+makes getting at the classic data less than convenient (i.e., one has
+to create a whole derived class just to get at the masks array). It
+makes little sense to expose the size of the table in the public
+interface while making the table itself protected, especially when the
+table is a constant object.
+
+The same argument can be made for the non-static protected member
+function table()
.
+
Proposed resolution:
+
+Make the ctype<char>::classic_table()
and
+ctype<char>::table()
member functions public by
+moving their declarations into the public section of the definition of
+specialization in 22.2.1.3 [facet.ctype.special] as shown below:
+
++ + + + + +static locale::id id; + static const size_t table_size = IMPLEMENTATION_DEFINED; ++protected:+ const mask* table() const throw(); + static const mask* classic_table() throw(); +protected: + +~ctype(); // virtual +virtual char do_toupper(char c) const; +
Section: 26.4 [rand] Status: WP + Submitter: P.J. Plauger Date: 2007-07-01
+View all other issues in [rand].
+View all issues with WP status.
+Discussion:
++N2111 +changes min/max in several places in random from member +functions to static data members. I believe this introduces +a needless backward compatibility problem between C++0X and +TR1. I'd like us to find new names for the static data members, +or perhaps change min/max to constexprs in C++0X. +
+ ++See N2391 and +N2423 +for some further discussion. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2423. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 20.2.2 [forward] Status: WP + Submitter: P.J. Plauger Date: 2007-07-01
+View other active issues in [forward].
+View all other issues in [forward].
+View all issues with WP status.
+Discussion:
++N1856 +defines struct identity in <utility> which clashes with +the traditional definition of struct identity in <functional> +(not standard, but a common extension from old STL). Be nice +if we could avoid this name clash for backward compatibility. +
+ + +Proposed resolution:
++Change 20.2.2 [forward]: +
+ +++ + + + + + +template <class T> struct identity +{ + typedef T type; + const T& operator()(const T& x) const; +}; ++++ +const T& operator()(const T& x) const; +++++Returns: x. +
+
Section: 23.3.1.2 [map.access] Status: WP + Submitter: Joe Gottman Date: 2007-07-03
+View all other issues in [map.access].
+View all issues with WP status.
+Discussion:
++map::at() need a complexity specification. +
+ + +Proposed resolution:
++Add the following to the specification of map::at(), 23.3.1.2 [map.access]: +
+++ + + + + ++Complexity: logarithmic. +
+
Section: 20.5.7 [meta.trans.other] Status: WP + Submitter: Thorsten Ottosen Date: 2007-07-08
+View other active issues in [meta.trans.other].
+View all other issues in [meta.trans.other].
+View all issues with WP status.
+Discussion:
++The current working draft has a type-trait decay in 20.5.7 [meta.trans.other]. +
+ ++Its use is to turn C++03 pass-by-value parameters into efficient C++0x +pass-by-rvalue-reference parameters. However, the current definition +introduces an incompatible change where the cv-qualification of the +parameter type is retained. The deduced type should loose such +cv-qualification, as pass-by-value does. +
+ + +Proposed resolution:
++In 20.5.7 [meta.trans.other] change the last sentence: +
+ ++ ++Otherwise the member typedef type equals remove_cv<U>::type. +
+In 20.4.1.3 [tuple.creation]/1 change: +
+ ++ + + + + + ++
where each Vi in VTypes is X& if, for the +corresponding type Ti in Types, +remove_cv<remove_reference<Ti>::type>::type equals +reference_wrapper<X>, otherwise Vi is +decay<Ti>::type.+Let Ui be decay<Ti>::type for each +Ti in Types. Then each Vi in VTypes +is X& if Ui equals +reference_wrapper<X>, otherwise Vi is +Ui. +
Section: 20.2.3 [pairs] Status: WP + Submitter: Thorsten Ottosen Date: 2007-07-08
+View all other issues in [pairs].
+View all issues with WP status.
+Discussion:
++The current draft has make_pair() in 20.2.3 [pairs]/16 +and make_tuple() in 20.4.1.3 [tuple.creation]. +make_tuple() detects the presence of +reference_wrapper<X> arguments and "unwraps" the reference in +such cases. make_pair() would OTOH create a +reference_wrapper<X> member. I suggest that the two +functions are made to behave similar in this respect to minimize +confusion. +
+ + +Proposed resolution:
++In 20.2 [utility] change the synopsis for make_pair() to read +
+ ++ +template <class T1, class T2> + pair<typename decay<T1>::typeV1,typename decay<T2>::typeV2> make_pair(T1&&, T2&&); +
+In 20.2.3 [pairs]/16 change the declaration to match the above synopsis. +Then change the 20.2.3 [pairs]/17 to: +
+ +++ + + + + + ++Returns: pair<
+typename decay<T1>::typeV1,typename decay<T2>::typeV2>(forward<T1>(x),forward<T2>(y)) where V1 and +V2 are determined as follows: Let Ui be +decay<Ti>::type for each Ti. Then each +Vi is X& if Ui equals +reference_wrapper<X>, otherwise Vi is +Ui. +
Section: 20.7.12.2 [util.smartptr.shared] Status: WP + Submitter: Peter Dimov Date: 2007-08-24
+View other active issues in [util.smartptr.shared].
+View all other issues in [util.smartptr.shared].
+View all issues with WP status.
+Discussion:
++A discussion on +comp.std.c++ +has identified a contradiction in the shared_ptr specification. +The shared_ptr move constructor and the cast functions are +missing postconditions for the get() accessor. +
+ +[ +Bellevue: +]
+ + +++ + ++Move to "ready", adopting the first (Peter's) proposed resolution. +
++Note to the project editor: there is an editorial issue here. The +wording for the postconditions of the casts is slightly awkward, and the +editor should consider rewording "If w is the return value...", e. g. as +"For a return value w...". +
+
Proposed resolution:
++Add to 20.7.12.2.1 [util.smartptr.shared.const]: +
+ +++ +shared_ptr(shared_ptr&& r); +template<class Y> shared_ptr(shared_ptr<Y>&& r); +++++Postconditions: *this shall contain the old value of r. r +shall be empty. r.get() == 0. +
+
+Add to 20.7.12.2.10 [util.smartptr.shared.cast]: +
+ +++ +template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const& r); +++++Postconditions: If w is the return value, +w.get() == static_cast<T*>(r.get()) && w.use_count() == r.use_count(). +
+
++ +template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r); +++++Postconditions: If w is the return value, w.get() == dynamic_cast<T*>(r.get()). +
+
++ +template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const& r); +++++Postconditions: If w is the return value, +w.get() == const_cast<T*>(r.get()) && w.use_count() == r.use_count(). +
+
+Alberto Ganesh Barbati has written an +alternative proposal +where he suggests (among other things) that the casts be respecified in terms of +the aliasing constructor as follows: +
+ ++Change 20.7.12.2.10 [util.smartptr.shared.cast]: +
+ +++ ++-2- Returns:
+If r is empty, an empty +shared_ptr<T>; otherwise, a shared_ptr<T> +object that stores static_cast<T*>(r.get()) and shares ownership with +r.shared_ptr<T>(r, static_cast<T*>(r.get()). +
++ ++-6- Returns: +
++
+- +
When dynamic_cast<T*>(r.get()) returns a nonzero value, +a shared_ptr<T> object that stores a copy +of it and shares ownership with r;- +
Otherwise, an empty shared_ptr<T> object.- If p = dynamic_cast<T*>(r.get()) is a non-null pointer, shared_ptr<T>(r, p);
+- Otherwise, shared_ptr<T>().
+
++ ++-10- Returns:
+If r is empty, an empty +shared_ptr<T>; otherwise, a shared_ptr<T> +object that stores const_cast<T*>(r.get()) and shares ownership with +r.shared_ptr<T>(r, const_cast<T*>(r.get()). +
+This takes care of the missing postconditions for the casts by bringing +in the aliasing constructor postcondition "by reference". +
+ + + + + + +Section: 26.4.7.1 [rand.util.seedseq] Status: WP + Submitter: Marc Paterno Date: 2007-08-25
+View other active issues in [rand.util.seedseq].
+View all other issues in [rand.util.seedseq].
+View all issues with WP status.
+Discussion:
++One of the motivations for incorporating seed_seq::size() +was to simplify the wording +in other parts of 26.4 [rand]. +As a side effect of resolving related issues, +all such references +to seed_seq::size() will have been excised. +More importantly, +the present specification is contradictory, +as "The number of 32-bit units the object can deliver" +is not the same as "the result of v.size()." +
+ ++See N2391 and +N2423 +for some further discussion. +
+ + +Proposed resolution:
++Adopt the proposed resolution in +N2423. +
+ + +[ +Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. +The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. +]
+ + + + + +Section: 25.3.7 [alg.min.max] Status: WP + Submitter: Matt Austern Date: 2007-08-30
+View all other issues in [alg.min.max].
+View all issues with WP status.
+Discussion:
++The complexity for minmax_element (25.3.7 [alg.min.max] par 16) says "At most max(2 * +(last - first ) - 2, 0) applications of the corresponding comparisons", +i.e. the worst case complexity is no better than calling min_element and +max_element separately. This is gratuitously inefficient. There is a +well known technique that does better: see section 9.1 of CLRS +(Introduction to Algorithms, by Cormen, Leiserson, Rivest, and Stein). +
+ + +Proposed resolution:
++Change 25.3.7 [alg.min.max] to: +
+ +++ + + + + + +template<class ForwardIterator> + pair<ForwardIterator, ForwardIterator> + minmax_element(ForwardIterator first , ForwardIterator last); +template<class ForwardIterator, class Compare> + pair<ForwardIterator, ForwardIterator> + minmax_element(ForwardIterator first , ForwardIterator last , Compare comp); +++++Returns: make_pair(m, M), where m is +
+min_element(first, last) or min_element(first, last, +comp)the first iterator in [first, +last) such that no iterator in the range refers to a smaller element, and +where M ismax_element(first, last) or +max_element(first, last, comp)the last iterator +in [first, last) such that no iterator in the range refers to a larger element. ++Complexity: At most
+max(2 * (last - first ) - 2, 0)+max(⌊(3/2) (N-1)⌋, 0) applications of the +correspondingcomparisonspredicate, where N is distance(first, last). +
Section: 26.7 [c.math] Status: WP + Submitter: Daniel Krügler Date: 2007-08-27
+View all other issues in [c.math].
+View all issues with WP status.
+Discussion:
++In the listing of 26.7 [c.math], table 108: Header <cmath> synopsis I miss +the following C99 functions (from 7.12.11.2): +
+ ++ +float nanf(const char *tagp); +long double nanl(const char *tagp); +
+(Note: These functions cannot be overloaded and they are also not +listed anywhere else) +
+ + +Proposed resolution:
++In 26.7 [c.math], table 108, section "Functions", add nanf and nanl +just after the existing entry nan. +
+ + + + + +Section: 20.7.11.4 [unique.ptr.compiletime] Status: WP + Submitter: Herb Sutter Date: 2007-10-04
+View all issues with WP status.
+Discussion:
++Please don't provide *_ptr<T[N]>. It doesn't enable any useful +bounds-checking (e.g., you could imagine that doing op++ on a +shared_ptr<T[N]> yields a shared_ptr<T[N-1]>, but that promising path +immediately falters on op-- which can't reliably dereference because we +don't know the lower bound). Also, most buffers you'd want to point to +don't have a compile-time known size. +
+ ++To enable any bounds-checking would require run-time information, with +the usual triplet: base (lower bound), current offset, and max offset +(upper bound). And I can sympathize with the point of view that you +wouldn't want to require this on *_ptr itself. But please let's not +follow the <T[N]> path, especially not with additional functions to +query the bounds etc., because this sets wrong user expectations by +embarking on a path that doesn't go all the way to bounds checking as it +seems to imply. +
+ ++If bounds checking is desired, consider a checked_*_ptr instead (e.g., +checked_shared_ptr). And make the interfaces otherwise identical so that +user code could easily #define/typedef between prepending checked_ on +debug builds and not doing so on release builds (for example). +
+ ++Note that some may object that checked_*_ptr may seem to make the smart +pointer more like vector, and we don't want two ways to spell vector. I +don't agree, but if that were true that would be another reason to +remove *_ptr<T[N]> which equally makes the smart pointer more like +std::array. :-) +
+ +[ +Bellevue: +]
+ + +++ + + +Suggestion that fixed-size array instantiations are going to fail at +compile time anyway (if we remove specialization) due to pointer decay, +at least that appears to be result from available compilers. +
++So concerns about about requiring static_assert seem unfounded. +
+After a little more experimentation with compiler, it appears that +fixed size arrays would only work at all if we supply these explicit +specialization. So removing them appears less breaking than originally +thought. +
++straw poll unanimous move to Ready. +
+
Proposed resolution:
++Change the synopsis under 20.7.11 [unique.ptr] p2: +
+ ++ +... +template<class T> struct default_delete; +template<class T> struct default_delete<T[]>; +template<class T, size_t N> struct default_delete<T[N]>;+ +template<class T, class D = default_delete<T>> class unique_ptr; +template<class T, class D> class unique_ptr<T[], D>; +template<class T, class D, size_t N> class unique_ptr<T[N], D>;+... +
+Remove the entire section 20.7.11.1.3 [unique.ptr.dltr.dflt2] default_delete<T[N]>. +
+ ++Remove the entire section 20.7.11.4 [unique.ptr.compiletime] unique_ptr for array objects with a compile time length +and its subsections: 20.7.11.4.1 [unique.ptr.compiletime.dtor], 20.7.11.4.2 [unique.ptr.compiletime.observers], +20.7.11.4.3 [unique.ptr.compiletime.modifiers]. +
+ + + + + + +Section: 20.7.12.2.9 [util.smartptr.shared.spec] Status: WP + Submitter: Howard Hinnant Date: 2007-10-10
+View all issues with WP status.
+Discussion:
++When the LWG looked at 674 in Kona the following note was made: +
+ ++ ++We may need to open an issue to deal with the question of +whether shared_ptr needs an rvalue swap. +
+This issue was opened in response to that note. +
+ ++I believe allowing rvalue shared_ptrs to swap is both +appropriate, and consistent with how other library components are currently specified. +
+ +[ +Bellevue: +]
+ + +++ + ++Concern that the three signatures for swap is needlessly complicated, +but this issue merely brings shared_ptr into equal complexity with the +rest of the library. Will open a new issue for concern about triplicate +signatures. +
++Adopt issue as written. +
+
Proposed resolution:
++Change the synopsis in 20.7.12.2 [util.smartptr.shared]: +
+ ++ +void swap(shared_ptr&& r); +... +template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b); +template<class T> void swap(shared_ptr<T>&& a, shared_ptr<T>& b); +template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>&& b); +
+Change 20.7.12.2.4 [util.smartptr.shared.mod]: +
+ ++ +void swap(shared_ptr&& r); +
+Change 20.7.12.2.9 [util.smartptr.shared.spec]: +
+ ++ + + + + +template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b); +template<class T> void swap(shared_ptr<T>&& a, shared_ptr<T>& b); +template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>&& b); +
Section: 18.7.5 [propagation] Status: WP + Submitter: Alisdair Meredith Date: 2007-10-10
+View other active issues in [propagation].
+View all other issues in [propagation].
+View all issues with WP status.
+Discussion:
++Without some lifetime guarantee, it is hard to know how this type can be +used. Very specifically, I don't see how the current wording would +guarantee and exception_ptr caught at the end of one thread could be safely +stored and rethrown in another thread - the original motivation for this +API. +
++(Peter Dimov agreed it should be clearer, maybe a non-normative note to +explain?) +
+ +[ +Bellevue: +]
+ + +++ + ++Agree the issue is real. +
++Intent is lifetime is similar to a shared_ptr (and we might even want to +consider explicitly saying that it is a shared_ptr< unspecified type >). +
++We expect that most implementations will use shared_ptr, and the +standard should be clear that the exception_ptr type is intended to be +something whose semantics are smart-pointer-like so that the user does +not need to worry about lifetime management. We still need someone to +draught those words - suggest emailing Peter Dimov. +
++Move to Open. +
+
Proposed resolution:
++Change 18.7.5 [propagation]/7: +
+ ++-7- Returns: An exception_ptr object that refers to the currently +handled exception or a copy of the currently handled exception, or a +null exception_ptr object if no exception is being handled. +The referenced object remains valid at least as long as there is an +exception_ptr that refers to it. +If the function needs to allocate memory and the attempt +fails, it returns an exception_ptr object that refers to an instance of +bad_alloc. It is unspecified whether the return values of two successive +calls to current_exception refer to the same exception object. [Note: +that is, it is unspecified whether current_exception creates a new copy +each time it is called. --end note] ++ + + + + +
Section: 18.7.5 [propagation] Status: WP + Submitter: Alisdair Meredith Date: 2007-10-10
+View other active issues in [propagation].
+View all other issues in [propagation].
+View all issues with WP status.
+Discussion:
++I understand that the attempt to copy an exception may run out of memory, +but I believe this is the only part of the standard that mandates failure +with specifically bad_alloc, as opposed to allowing an +implementation-defined type derived from bad_alloc. For instance, the Core +language for a failed new expression is: +
++++Any other allocation function that fails to allocate storage shall indicate +failure only by throwing an exception of a type that would match a handler +(15.3) of type std::bad_alloc (18.5.2.1). +
+
+I think we should allow similar freedom here (or add a blanket +compatible-exception freedom paragraph in 17) +
++I prefer the clause 17 approach myself, and maybe clean up any outstanding +wording that could also rely on it. +
++Although filed against a specific case, this issue is a problem throughout +the library. +
+ +[ +Bellevue: +]
+ + +++ + ++Is issue bigger than library? +
++No - Core are already very clear about their wording, which is inspiration for the issue. +
++While not sold on the original 18.7.5 use case, the generalised 17.4.4.8 wording is the real issue. +
++Accept the broad view and move to ready +
+
Proposed resolution:
++Add the following exemption clause to 17.4.4.9 [res.on.exception.handling]: +
+ ++A function may throw a type not listed in its Throws clause so long as it is +derived from a class named in the Throws clause, and would be caught by an +exception handler for the base type. ++ + + + + +
Section: 20.5.4.3 [meta.unary.prop] Status: WP + Submitter: Alisdair Meredith Date: 2007-10-10
+View all other issues in [meta.unary.prop].
+View all issues with WP status.
+Discussion:
++Unfortunately a class can have multiple copy constructors, and I believe to +be useful this trait should only return true is ALL copy constructors are +no-throw. +
++For instance: +
+++ + +struct awkward { + awkward( const awkward & ) throw() {} + awkward( awkward & ) { throw "oops"; } }; ++
Proposed resolution:
++Change 20.5.4.3 [meta.unary.prop]: +
+ +++ +has_trivial_copy_constructor++T is a trivial type (3.9) or a reference type or a class type+with a trivial copy constructor+where all copy constructors are trivial (12.8). +
++ +has_trivial_assign++T is neither const nor a reference type, and T is a trivial type (3.9) +or a class type+with a trivial copy assignment operatorwhere all copy assignment operators are trivial (12.8). +
++ +has_nothrow_copy_constructor++has_trivial_copy_constructor<T>::value is true or T is a class type+with +awhere all copy constructorsthat isare +known not to throw any exceptions or T is an +array of such a class type +
++ + + + + + +has_nothrow_assign++T is neither const nor a reference type, and +has_trivial_assign<T>::value is true or T is a class type+with a+where all copy +assignment operators takeingan lvalue of type T that is known not to +throw any exceptions or T is an array of such a class type. +
Section: 23.2.6.2 [vector.capacity], 21.3.4 [string.capacity] Status: WP + Submitter: Beman Dawes Date: 2007-10-31
+View all other issues in [vector.capacity].
+View all issues with WP status.
+Discussion:
++A std::vector can be shrunk-to-fit via the swap idiom: +
+ ++ +vector<int> v; +... +v.swap(vector<int>(v)); // shrink to fit ++++or: +
vector<int>(v).swap(v); // shrink to fit ++++or: +
swap(v, vector<int>(v)); // shrink to fit ++
+A non-binding request for shrink-to-fit can be made to a std::string via: +
+ ++ +string s; +... +s.reserve(0); +
+Neither of these is at all obvious to beginners, and even some +experienced C++ programmers are not aware that shrink-to-fit is +trivially available. +
++Lack of explicit functions to perform these commonly requested +operations makes vector and string less usable for non-experts. Because +the idioms are somewhat obscure, code readability is impaired. It is +also unfortunate that two similar vector-like containers use different +syntax for the same operation. +
++The proposed resolution addresses these concerns. The proposed function +takes no arguments to keep the solution simple and focused. +
+ + +Proposed resolution:
++To Class template basic_string 21.3 [basic.string] synopsis, +Class template vector 23.2.6 [vector] synopsis, and Class +vector<bool> 23.2.7 [vector.bool] synopsis, add: +
+ ++ ++void shrink_to_fit(); +
+To basic_string capacity 21.3.4 [string.capacity] and vector +capacity 23.2.6.2 [vector.capacity], add: +
+ +++ +void shrink_to_fit(); +++Remarks: shrink_to_fit is a non-binding request to reduce +capacity() to size(). [Note: The request is non-binding to +allow latitude for implementation-specific optimizations. +-- end note] ++
[ +850 has been added to deal with this issue with respect to deque. +]
+ + + + + + +Section: 23.1 [container.requirements] Status: WP + Submitter: Jens Maurer Date: 2007-11-06
+View other active issues in [container.requirements].
+View all other issues in [container.requirements].
+View all issues with WP status.
+Discussion:
++23.1 [container.requirements] says: +
+ ++-12- Objects passed to member functions of a container as rvalue references shall not be elements of that container. No +diagnostic required. ++ +
+A reference is not an object, but this sentence appears to claim so. +
+ ++What is probably meant here: +
++An object bound to an rvalue +reference parameter of a member function of a container shall not be +an element of that container; no diagnostic required. ++ + + +
Proposed resolution:
++Change 23.1 [container.requirements]: +
+ ++-12-+ + + + + + +Objects passed to member functions of a container as rvalue references shall not be elements+An object bound to an rvalue +reference parameter of a member function of a container shall not be +an element +of that container.;Nno +diagnostic required. +
Section: 23.4.1.2 [unord.map.elem] Status: WP + Submitter: Joe Gottman Date: 2007-11-15
+View all issues with WP status.
+Discussion:
++The new member function at() was recently added to std::map(). It acts +like operator[](), except it throws an exception when the input key is +not found. It is useful when the map is const, the value_type of the +key doesn't have a default constructor, it is an error if the key is +not found, or the user wants to avoid accidentally adding an element to +the map. For exactly these same reasons, at() would be equally useful +in std::unordered_map. +
+ + +Proposed resolution:
++Add the following functions to the definition of unordered_map under "lookup" (23.4.1 [unord.map]): +
+ ++ +mapped_type& at(const key_type& k); +const mapped_type &at(const key_type &k) const; +
+Add the following definitions to 23.4.1.2 [unord.map.elem]: +
+ +++ +mapped_type& at(const key_type& k); +const mapped_type &at(const key_type &k) const; +++++Returns: A reference to x.second, where x is the (unique) element +whose key is equivalent to k. +
++Throws: An exception object of type out_of_range if no such element +is present. +
+
[ +Bellevue: Editorial note: the "(unique)" differs from map. +]
+ + + + + + + +Section: 23.1 [container.requirements], 23.1.5.1 [unord.req.except] Status: WP + Submitter: Ion Gaztañaga Date: 2007-12-22
+View other active issues in [container.requirements].
+View all other issues in [container.requirements].
+View all issues with WP status.
+Discussion:
++23.1 [container.requirements]p10 states: +
+ +++ ++Unless otherwise specified (see 23.2.2.3 and 23.2.5.4) all container types defined in this clause meet the following +additional requirements: +
++ +
+- [...]
+ +- no erase(), pop_back() or pop_front() function throws an exception.
+ +
+23.2.2.3 [deque.modifiers] and 23.2.6.4 [vector.modifiers] offer +additional guarantees for deque/vector insert() and +erase() members. However, 23.1 [container.requirements]p10 +does not mention 23.1.5.1 [unord.req.except] that specifies exception +safety guarantees +for unordered containers. In addition, 23.1.5.1 [unord.req.except]p1 +offers the following guaratee for +erase(): +
+ ++No erase() function throws an exception unless that exception +is thrown by the container's Hash or Pred object (if any). ++ +
+Summary: +
+ ++According to 23.1 [container.requirements]p10 no +erase() function should throw an exception unless otherwise +specified. Although does not explicitly mention 23.1.5.1 [unord.req.except], this section offers additional guarantees +for unordered containers, allowing erase() to throw if +predicate or hash function throws. +
+ ++In contrast, associative containers have no exception safety guarantees +section so no erase() function should throw, including +erase(k) that needs to use the predicate function to +perform its work. This means that the predicate of an associative +container is not allowed to throw. +
+ ++So: +
+ +Proposed resolution:
++Create a new sub-section of 23.1.4 [associative.reqmts] (perhaps [associative.req.except]) titled "Exception +safety guarantees". +
+ +++ ++1 For associative containers, no clear() function throws an exception. +erase(k) does not throw an exception unless that exception is thrown by +the container's Pred object (if any). +
+ ++2 For associative containers, if an exception is thrown by any operation +from within an insert() function inserting a single element, the +insert() function has no effect. +
+ ++3 For associative containers, no swap function throws an exception +unless that exception is thrown by the copy constructor or copy +assignment operator of the container's Pred object (if any). +
+
+Change 23.1.5.1 [unord.req.except]p1: +
+ ++For unordered associative containers, no clear() function +throws an exception.+ +Noerase(k) +functiondoes not throwsan exception +unless that exception is thrown by the container's Hash or Pred object +(if any). +
+Change 23.1 [container.requirements]p10 to add references to new sections: +
+ ++Unless otherwise specified (see [deque.modifiers], ++ +and[vector.modifiers], [associative.req.except], +[unord.req.except]) all container types defined in this clause meet +the following additional requirements: +
+Change 23.1 [container.requirements]p10 referring to swap: +
+ +++ + + + + + ++
+- +no swap() function throws an exception
+unless that exception is thrown +by the copy constructor or assignment operator of the container's +Compare object (if any; see [associative.reqmts]). +
Section: 29.3.3 [atomics.types.generic] Status: WP + Submitter: Alberto Ganesh Barbati Date: 2007-12-28
+View all issues with WP status.
+Discussion:
++in the latest publicly available draft, paper +N2641, +in section 29.3.3 [atomics.types.generic], the following specialization of the template +atomic<> is provided for pointers: +
+ ++ +template <class T> struct atomic<T*> : atomic_address { + T* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst) volatile; + T* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst) volatile; + + atomic() = default; + constexpr explicit atomic(T); + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + + T* operator=(T*) volatile; + T* operator++(int) volatile; + T* operator--(int) volatile; + T* operator++() volatile; + T* operator--() volatile; + T* operator+=(ptrdiff_t) volatile; + T* operator-=(ptrdiff_t) volatile; +}; +
+First of all, there is a typo in the non-default constructor which +should take a T* rather than a T. +
+ ++As you can see, the specialization redefine and therefore hide a few +methods from the base class atomic_address, namely fetch_add, fetch_sub, +operator=, operator+= and operator-=. That's good, but... what happened +to the other methods, in particular these ones: +
+ ++ +void store(T*, memory_order = memory_order_seq_cst) volatile; +T* load( memory_order = memory_order_seq_cst ) volatile; +T* swap( T*, memory_order = memory_order_seq_cst ) volatile; +bool compare_swap( T*&, T*, memory_order, memory_order ) volatile; +bool compare_swap( T*&, T*, memory_order = memory_order_seq_cst ) volatile; +
+By reading paper +N2427 "C++ Atomic Types and Operations", +I see that the +definition of the specialization atomic<T*> matches the one in the +draft, but in the example implementation the methods load(), swap() +and compare_swap() are indeed present. +
+ ++Strangely, the example implementation does not redefine the method +store(). It's true that a T* is always convertible to void*, but not +hiding the void* signature from the base class makes the class +error-prone to say the least: it lets you assign pointers of any type to +a T*, without any hint from the compiler. +
+ ++Is there a true intent to remove them from the specialization or are +they just missing from the definition because of a mistake? +
+ +[ +Bellevue: +]
+ + +++ + ++The proposed revisions are accepted. +
++Further discussion: why is the ctor labeled "constexpr"? Lawrence said +this permits the object to be statically initialized, and that's +important because otherwise there would be a race condition on +initialization. +
+
Proposed resolution:
++Change the synopsis in 29.3.3 [atomics.types.generic]: +
+ ++ + + + + + +template <class T> struct atomic<T*> : atomic_address { + void store(T*, memory_order = memory_order_seq_cst) volatile; + T* load( memory_order = memory_order_seq_cst ) volatile; + T* swap( T*, memory_order = memory_order_seq_cst ) volatile; + bool compare_swap( T*&, T*, memory_order, memory_order ) volatile; + bool compare_swap( T*&, T*, memory_order = memory_order_seq_cst ) volatile; + + T* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst) volatile; + T* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst) volatile; + + atomic() = default; + constexpr explicit atomic(T*); + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + + T* operator=(T*) volatile; + T* operator++(int) volatile; + T* operator--(int) volatile; + T* operator++() volatile; + T* operator--() volatile; + T* operator+=(ptrdiff_t) volatile; + T* operator-=(ptrdiff_t) volatile; +}; +
Section: 20.6.15 [func.wrap] Status: WP + Submitter: Daniel Krügler Date: 2008-01-10
+View all issues with WP status.
+Discussion:
++It is expected that typical implementations of std::function will +use dynamic memory allocations at least under given conditions, +so it seems appropriate to change the current lvalue swappabilty of +this class to rvalue swappability. +
+ + +Proposed resolution:
++In 20.6 [function.objects], header <functional> synopsis, just below of +
+ ++ +template<class R, class... ArgTypes> + void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&); +template<class R, class... ArgTypes> + void swap(function<R(ArgTypes...)>&&, function<R(ArgTypes...)>&); +template<class R, class... ArgTypes> + void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&&); +
+In 20.6.15.2 [func.wrap.func] class function definition, change +
+ ++ +void swap(function&&); +
+In 20.6.15.2 [func.wrap.func], just below of +
+ ++ +template <class R, class... ArgTypes> + void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&); +template <class R, class... ArgTypes> + void swap(function<R(ArgTypes...)>&&, function<R(ArgTypes...)>&); +template <class R, class... ArgTypes> + void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&&); +
+In 20.6.15.2.2 [func.wrap.func.mod] change +
+ ++ +void swap(function&& other); +
+In 20.6.15.2.7 [func.wrap.func.alg] add the two overloads +
+ ++ + + + + + +template<class R, class... ArgTypes> + void swap(function<R(ArgTypes...)>&& f1, function<R(ArgTypes...)>& f2); +template<class R, class... ArgTypes> + void swap(function<R(ArgTypes...)>& f1, function<R(ArgTypes...)>&& f2); +
Section: 20.4.1.4 [tuple.helper] Status: WP + Submitter: Alisdair Meredith Date: 2008-01-16
+View all issues with WP status.
+Discussion:
++The tuple element access API identifies the element in the sequence +using signed integers, and then goes on to enforce the requirement that +I be >= 0. There is a much easier way to do this - declare I as +unsigned. +
+
+In fact the proposal is to use std::size_t
, matching the type used in the tuple_size API.
+
+A second suggestion is that it is hard to imagine an API that deduces +and index at compile time and returns a reference throwing an exception. +Add a specific Throws: Nothing paragraph to each element +access API. +
+
+In addition to tuple
, update the API applies to
+pair
and array
, and should be updated
+accordingly.
+
+A third observation is that the return type of the get
+functions for std::pair
is pseudo-code, but it is not
+clearly marked as such. There is actually no need for pseudo-code as
+the return type can be specified precisely with a call to
+tuple_element
. This is already done for
+std::tuple
, and std::array
does not have a
+problem as all elements are of type T
.
+
Proposed resolution:
++Update header <utility> synopsis in 20.2 [utility] +
+// 20.2.3, tuple-like access to pair: +template <class T> class tuple_size; +template <+intsize_t I, class T> class tuple_element; + +template <class T1, class T2> struct tuple_size<std::pair<T1, T2> >; +template <class T1, class T2> struct tuple_element<0, std::pair<T1, T2> >; +template <class T1, class T2> struct tuple_element<1, std::pair<T1, T2> >; + +template<intsize_t I, class T1, class T2> +Ptypename tuple_element<I, std::pair<T1, T2> >::type & get(std::pair<T1, T2>&); +template<intsize_t I, class T1, class T2> + constPtypename tuple_element<I, std::pair<T1, T2> >::type & get(const std::pair<T1, T2>&); +
+Update 20.2.3 [pairs] Pairs +
+template<+intsize_t I, class T1, class T2> +Ptypename tuple_element<I, std::pair<T1, T2> >::type & get(pair<T1, T2>&); +template<intsize_t I, class T1, class T2> + constPtypename tuple_element<I, std::pair<T1, T2> >::type & get(const pair<T1, T2>&); +
+24 Return type: If
+I == 0
then P
is T1
, if I == 1
then P
is T2
, and otherwise the program is ill-formed.
+25 Returns: If I == 0
returns p.first
, otherwise if I == 1
returns p.second
, and otherwise the program is ill-formed.
+
+Throws: Nothing. +
+ + ++Update header <tuple> synopsis in 20.4 [tuple] with a APIs as below: +
+template <+ +intsize_t I, class T> class tuple_element; // undefined +template <intsize_t I, class... Types> class tuple_element<I, tuple<Types...> >; + +// 20.3.1.4, element access: +template <intsize_t I, class... Types> + typename tuple_element<I, tuple<Types...> >::type& get(tuple<Types...>&); +template <intsize_t I, class ... types> + typename tuple_element<I, tuple<Types...> >::type const& get(const tuple<Types...>&); +
+Update 20.4.1.4 [tuple.helper] Tuple helper classes +
+template <+intsize_t I, class... Types> +class tuple_element<I, tuple<Types...> > { +public: + typedef TI type; +};
+1 Requires:
. The program is ill-formed if 0 <= I and I < sizeof...(Types)I
is out of bounds.
+
+2 Type: TI
is the type of the I
th element of Types
, where indexing is zero-based.
+
+Update 20.4.1.5 [tuple.elem] Element access +
+template <+1 Requires:intsize_t I, class... types > +typename tuple_element<I, tuple<Types...> >::type& get(tuple<Types...>& t); +
0 <= I and I < sizeof...(Types)
. The program is ill-formed if I
is out of bounds.
+
+2 Returns: A reference to the I
th element of t
, where indexing is zero-based.
+
template <+intsize_t I, class... types> +typename tuple_element<I, tuple<Types...> >::type const& get(const tuple<Types...>& t); +
+3 Requires:
. The program is ill-formed if 0 <= I and I < sizeof...(Types)I
is out of bounds.
+
+4 Returns: A const reference to the I
th element of t
, where indexing is zero-based.
+
+Throws: Nothing. +
+ + ++Update header <array> synopsis in 20.2 [utility] +
+template <class T> class tuple_size; // forward declaration +template <+ +intsize_t I, class T> class tuple_element; // forward declaration +template <class T, size_t N> + struct tuple_size<array<T, N> >; +template <intsize_t I, class T, size_t N> + struct tuple_element<I, array<T, N> >; +template <intsize_t I, class T, size_t N> + T& get(array<T, N>&); +template <intsize_t I, class T, size_t N> + const T& get(const array<T, N>&); +
+Update 23.2.1.6 [array.tuple] Tuple interface to class template array +
+tuple_element<size_t I, array<T, N> >::type ++
+3 Requires:
The program is ill-formed if 0 <= I < N.I
is out of bounds.
+
+4 Value: The type T
.
+
template <+intsize_t I, class T, size_t N> T& get(array<T, N>& a); +
+5 Requires:
. The program is ill-formed if 0 <= I < NI
is out of bounds.
+
+Returns: A reference to the I
th element of a
, where indexing is zero-based.
+
+Throws: Nothing. +
+template <+intsize_t I, class T, size_t N> const T& get(const array<T, N>& a); +
+6 Requires:
. The program is ill-formed if 0 <= I < NI
is out of bounds.
+
+7 Returns: A const reference to the I
th element of a
, where indexing is zero-based.
+
+Throws: Nothing. +
+ + +[ +Bellevue: Note also that the phrase "The program is ill-formed if I is +out of bounds" in the requires clauses are probably unnecessary, and +could be removed at the editor's discretion. Also std:: qualification +for pair is also unnecessary. +]
+ + + + +Section: 29.4 [atomics.types.operations] Status: WP + Submitter: Lawrence Crowl Date: 2008-01-21
+View all other issues in [atomics.types.operations].
+View all issues with WP status.
+Discussion:
++The load functions are defined as +
+ ++ +C atomic_load(volatile A* object); +C atomic_load_explicit(volatile A* object, memory_order); +C A::load(memory_order order = memory_order_seq_cst) volatile; +
+which prevents their use in const contexts. +
+ +[ +post Bellevue Peter adds: +]
+ + +++ + + ++Issue 777 suggests making atomic_load operate on const objects. There is a +subtle point here. Atomic loads do not generally write to the object, except +potentially for the memory_order_seq_cst constraint. Depending on the +architecture, a dummy write with the same value may be required to be issued +by the atomic load to maintain sequential consistency. This, in turn, may +make the following code: +
+ ++ +const atomic_int x{}; + +int main() +{ + x.load(); +} ++dump core under a straightforward implementation that puts const objects in +a read-only section. +
++There are ways to sidestep the problem, but it needs to be considered. +
++The tradeoff is between making the data member of the atomic types +mutable and requiring the user to explicitly mark atomic members as +mutable, as is already the case with mutexes. +
+
Proposed resolution:
++Add the const qualifier to *object and *this. +
+ ++ + + + + + +C atomic_load(const volatile A* object); +C atomic_load_explicit(const volatile A* object, memory_order); +C A::load(memory_order order = memory_order_seq_cst) const volatile; +
Section: 23.3.5.1 [bitset.cons] Status: WP + Submitter: Thorsten Ottosen Date: 2008-01-24
+View all other issues in [bitset.cons].
+View all issues with WP status.
+Duplicate of: 116
+Discussion:
++A small issue with std::bitset: it does not have any constructor +taking a string literal, which is clumsy and looks like an oversigt when +we tried to enable uniform use of string and const char* in the library. +
+ ++Suggestion: Add +
+ ++ +explicit bitset( const char* str ); +
+to std::bitset. +
+ + +Proposed resolution:
++Add to synopsis in 23.3.5 [template.bitset] +
+ ++ +explicit bitset( const char* str ); +
+Add to synopsis in 23.3.5.1 [bitset.cons] +
+ ++ + + + + + +explicit bitset( const char* str ); +++Effects: Constructs a bitset as if bitset(string(str)). +
+
Section: 26.3.7 [complex.value.ops] Status: WP + Submitter: Daniel Krügler Date: 2008-01-26
+View all other issues in [complex.value.ops].
+View all issues with WP status.
+Discussion:
++A comparision of the N2461 header <complex> synopsis ([complex.synopsis]) +with the C99 standard (ISO 9899, 2nd edition and the two corrigenda) show +some complex functions that are missing in C++. These are: +
+ +cerf cerfc cexp2 +cexpm1 clog10 clog1p +clog2 clgamma ctgamma ++
+I propose that at least the required cproj overloads are provided as equivalent +C++ functions. This addition is easy to do in one sentence (delegation to C99 +function). +
+ ++Please note also that the current entry polar +in 26.3.9 [cmplx.over]/1 +should be removed from the mentioned overload list. It does not make sense to require that a +function already expecting scalar arguments +should cast these arguments into corresponding +complex<T> arguments, which are not accepted by +this function. +
+ + +Proposed resolution:
++In 26.3.1 [complex.synopsis] add just between the declaration of conj and fabs: +
+ ++ +template<class T> complex<T> conj(const complex<T>&); +template<class T> complex<T> proj(const complex<T>&); +template<class T> complex<T> fabs(const complex<T>&); +
+In 26.3.7 [complex.value.ops] just after p.6 (return clause of conj) add: +
+ +++ +template<class T> complex<T> proj(const complex<T>& x); +++ +Effects: Behaves the same as C99 function cproj, defined in +subclause 7.3.9.4." ++
+In 26.3.9 [cmplx.over]/1, add one further entry proj to +the overload list. +
+ +++ + + + + + ++The following function templates shall have additional overloads: +
++arg norm +conjpolarproj +imag real +
Section: 26.4.7.1 [rand.util.seedseq] Status: WP + Submitter: Daniel Krügler Date: 2008-01-27
+View other active issues in [rand.util.seedseq].
+View all other issues in [rand.util.seedseq].
+View all issues with WP status.
+Discussion:
++Part of the resolution of n2423, issue 8 was the proposal to +extend the seed_seq constructor accepting an input range +as follows (which is now part of N2461): +
+ ++ +template<class InputIterator, +size_t u = numeric_limits<iterator_traits<InputIterator>::value_type>::digits> +seed_seq(InputIterator begin, InputIterator end); +
+First, the expression iterator_traits<InputIterator>::value_type +is invalid due to missing typename keyword, which is easy to +fix. +
+ ++Second (and worse), while the language now supports default +template arguments of function templates, this customization +point via the second size_t template parameter is of no advantage, +because u can never be deduced, and worse - because it is a +constructor function template - it can also never be explicitly +provided (14.8.1 [temp.arg.explicit]/7). +
+ ++The question arises, which advantages result from a compile-time +knowledge of u versus a run time knowledge? If run time knowledge +suffices, this parameter should be provided as normal function +default argument [Resolution marked (A)], if compile-time knowledge +is important, this could be done via a tagging template or more +user-friendly via a standardized helper generator function +(make_seed_seq), which allows this [Resolution marked (B)]. +
+ +[ +Bellevue: +]
+ + +++ ++Fermilab does not have a strong opinion. Would prefer to go with +solution A. Bill agrees that solution A is a lot simpler and does the +job. +
++Proposed Resolution: Accept Solution A. +
+
+Issue 803 claims to make this issue moot. +
+ + + +Proposed resolution:
++In 26.4.7.1 [rand.util.seedseq]/2, class seed_seq synopsis replace: +
+ ++ +class seed_seq +{ +public: + ... + template<class InputIterator, + size_t u = numeric_limits<iterator_traits<InputIterator>::value_type>::digits> + seed_seq(InputIterator begin, InputIterator end, + size_t u = numeric_limits<typename iterator_traits<InputIterator>::value_type>::digits); + ... +}; +
+and do a similar replacement in the member description between +p.3 and p.4. +
++In 26.4.7.1 [rand.util.seedseq]/2, class seed_seq synopsis and in the +member description between p.3 and p.4 replace: +
+ ++ +template<class InputIterator, + size_t u = numeric_limits<iterator_traits<InputIterator>::value_type>::digits> + seed_seq(InputIterator begin, InputIterator end); +template<class InputIterator, size_t u> +seed_seq(InputIterator begin, InputIterator end, implementation-defined s); +
+In 26.4.2 [rand.synopsis], header <random> synopsis, immediately after the +class seed_seq declaration and in 26.4.7.1 [rand.util.seedseq]/2, immediately +after the class seed_seq definition add: +
+ ++ +template<size_t u, class InputIterator> + seed_seq make_seed_seq(InputIterator begin, InputIterator end); +
+In 26.4.7.1 [rand.util.seedseq], just before p.5 insert two paragraphs: +
+ +++ ++The first constructor behaves as if it would provide an +integral constant expression u of type size_t of value +numeric_limits<typename iterator_traits<InputIterator>::value_type>::digits. +
++The second constructor uses an implementation-defined mechanism +to provide an integral constant expression u of type size_t and +is called by the function make_seed_seq. +
+
+In 26.4.7.1 [rand.util.seedseq], just after the last paragraph add: +
+ +++ +template<size_t u, class InputIterator> + seed_seq make_seed_seq(InputIterator begin, InputIterator end); +++++where u is used to construct an object s of implementation-defined type. +
++Returns: seed_seq(begin, end, s); +
+
Section: 30.2.1.1 [thread.thread.id] Status: WP + Submitter: Hans Boehm Date: 2008-02-01
+View all issues with WP status.
+Discussion:
++The current working paper +(N2497, +integrated just before Bellevue) is +not completely clear whether a given thread::id value may be reused once +a thread has exited and has been joined or detached. Posix allows +thread ids (pthread_t values) to be reused in this case. Although it is +not completely clear whether this originally was the right decision, it +is clearly the established practice, and we believe it was always the +intent of the C++ threads API to follow Posix and allow this. Howard +Hinnant's example implementation implicitly relies on allowing reuse +of ids, since it uses Posix thread ids directly. +
+ ++It is important to be clear on this point, since it the reuse of thread +ids often requires extra care in client code, which would not be +necessary if thread ids were unique across all time. For example, a +hash table indexed by thread id may have to be careful not to associate +data values from an old thread with a new one that happens to reuse the +id. Simply removing the old entry after joining a thread may not be +sufficient, if it creates a visible window between the join and removal +during which a new thread with the same id could have been created and +added to the table. +
+ +[ +post Bellevue Peter adds: +]
+ + +++ + + ++There is a real issue with thread::id reuse, but I urge the LWG to +reconsider fixing this by disallowing reuse, rather than explicitly allowing +it. Dealing with thread id reuse is an incredibly painful exercise that +would just force the world to reimplement a non-conflicting thread::id over +and over. +
++In addition, it would be nice if a thread::id could be manipulated +atomically in a lock-free manner, as motivated by the recursive lock +example: +
+ ++http://www.decadentplace.org.uk/pipermail/cpp-threads/2006-August/001091.html +
+
Proposed resolution:
++Add a sentence to 30.2.1.1 [thread.thread.id]/p1: +
+ +++ + + + + ++An object of type
+thread::id
provides +a unique identifier for each thread of execution +and a single distinct value for all thread objects +that do not represent a thread of execution ([thread.threads.class]). +Each thread of execution has athread::id
+that is not equal to thethread::id
+of other threads of execution +and that is not equal to +thethread::id
ofstd::thread
objects +that do not represent threads of execution. +The library may reuse the value of athread::id
of a +terminated thread that can no longer be joined. +
Section: 26.4.4.4 [rand.adapt.xor] Status: WP + Submitter: P.J. Plauger Date: 2008-02-09
+View all other issues in [rand.adapt.xor].
+View all issues with WP status.
+Discussion:
++xor_combine_engine(result_type) should be explicit. (Obvious oversight.) +
+ +[ +Bellevue: +]
+ + ++Non-controversial. Bill is right, but Fermilab believes that this is +easy to use badly and hard to use right, and so it should be removed +entirely. Got into TR1 by well defined route, do we have permission to +remove stuff? Should probably check with Jens, as it is believed he is +the originator. Broad consensus that this is not a robust engine +adapter. ++ + +
Proposed resolution:
++Remove xor_combine_engine from synopsis of 26.4.2 [rand.synopsis]. +
++Remove 26.4.4.4 [rand.adapt.xor] xor_combine_engine. +
+ + + + + +Section: 26.4.8.5.2 [rand.dist.samp.pconst] Status: WP + Submitter: P.J. Plauger Date: 2008-02-09
+View other active issues in [rand.dist.samp.pconst].
+View all other issues in [rand.dist.samp.pconst].
+View all issues with WP status.
+Discussion:
++piecewise_constant_distribution is undefined for a range with just one +endpoint. (Probably should be the same as an empty range.) +
+ + +Proposed resolution:
++Change 26.4.8.5.2 [rand.dist.samp.pconst] paragraph 3b: +
+ ++b) If firstB == lastB or the sequence w has the length zero, ++ + + + + +
Section: D.8 [depr.lib.binders] Status: WP + Submitter: Daniel Krügler Date: 2008-02-14
+View all other issues in [depr.lib.binders].
+View all issues with WP status.
+Discussion:
++N2521 +and its earlier predecessors have moved the old binders from +[lib.binders] to D.8 [depr.lib.binders] thereby introducing some renaming +of the template parameter names (Operation -> Fn). During this +renaming process the protected data member op was also renamed to +fn, which seems as an unnecessary interface breakage to me - even if +this user access point is probably rarely used. +
+ + +Proposed resolution:
++Change D.8.1 [depr.lib.binder.1st]: +
+ +++ +template <class Fn> +class binder1st + : public unary_function<typename Fn::second_argument_type, + typename Fn::result_type> { +protected: + Fn+ +fnop; + typename Fn::first_argument_type value; +public: + binder1st(const Fn& x, + const typename Fn::first_argument_type& y); + typename Fn::result_type + operator()(const typename Fn::second_argument_type& x) const; + typename Fn::result_type + operator()(typename Fn::second_argument_type& x) const; +}; ++++-1- The constructor initializes
+fnop with x and value with y. ++-2- operator() returns
+fnop(value,x). +
+Change D.8.3 [depr.lib.binder.2nd]: +
+ +++ + + + + + + \ No newline at end of filetemplate <class Fn> +class binder2nd + : public unary_function<typename Fn::first_argument_type, + typename Fn::result_type> { +protected: + Fn+ +fnop; + typename Fn::second_argument_type value; +public: + binder2nd(const Fn& x, + const typename Fn::second_argument_type& y); + typename Fn::result_type + operator()(const typename Fn::first_argument_type& x) const; + typename Fn::result_type + operator()(typename Fn::first_argument_type& x) const; +}; ++++-1- The constructor initializes
+fnop with x and value with y. ++-2- operator() returns
+fnop(value,x). +