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 @@ + + + + + +C++ Standard Library Defect Report List + + + + + + + + + + + + + + + + + + + +
Doc. no.N2728=08-0238
Date:2008-08-24
Project:Programming Language C++
Reply to:Howard Hinnant <howard.hinnant@gmail.com>
+

C++ Standard Library Defect Report List (Revision R59)

+ +

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.

+ +

Revision History

+ + +

Defect Reports

+
+

1. C library linkage editing oversight

+

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.

+
+ + + + + +
+

3. Atexit registration during atexit() call is not described

+

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.

+ + + + + +
+

5. String::compare specification questionable

+

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.

+ + + + + +
+

7. String clause minor problems

+

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."

+ + + + + +
+

8. Locale::global lacks guarantee

+

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().

+ +
+ + + + + +
+

9. Operator new(0) calls should not yield the same pointer

+

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.

+ + + + + +
+

11. Bitset minor problems

+

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]. +

+ + + + + +
+

13. Eos refuses to die

+

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()"

+ + + + + +
+

14. Locale::combine should be 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::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; 
+
+ + + + + +
+

15. Locale::name requirement inconsistent

+

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())". +

+ + + + + +
+

16. Bad ctype_byname<char> decl

+

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].

+ + + + + +
+

17. Bad bool parsing

+

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]

+
+ + + + + +
+

18. Get(...bool&) omitted

+

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].

+ + + + + +
+

19. "Noconv" definition too vague

+

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).

+
+ + + + + +
+

20. Thousands_sep returns wrong type

+

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".

+ + + + + +
+

21. Codecvt_byname<> instantiations

+

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> 
+
+ + + + + +
+

22. Member open vs. flags

+

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.

+ + + + + + +
+

24. "do_convert" doesn't exist

+

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".

+ + + + + +
+

25. String operator<< uses width() value wrong

+

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(); +..."

+ + + + + +
+

26. Bad sentry example

+

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.

+ + + + + +
+

27. String::erase(range) yields wrong iterator

+

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.

+
+ + + + + +
+

28. Ctype<char>is ambiguous

+

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].

+
+ + + + + +
+

29. Ios_base::init doesn't exist

+

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

+
+ + + + + +
+

30. Wrong header for LC_*

+

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>".

+ + + + + +
+

31. Immutable locale values

+

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.

+
+ + + + + +
+

32. Pbackfail description inconsistent

+

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.

+ + + + + +
+

33. Codecvt<> mentions from_type

+

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.

+
+ + + + + +
+

34. True/falsename() not in ctype<>

+

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(); 
+
+ + + + + +
+

35. No manipulator unitbuf in synopsis

+

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); 
+
+ + + + + +
+

36. Iword & pword storage lifetime omitted

+

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.

+ + + + + +
+

37. Leftover "global" reference

+

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)

+
+ + + + + +
+

38. Facet definition incomplete

+

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..." +]

+ + + + + + + +
+

39. istreambuf_iterator<>::operator++(int) definition garbled

+

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.

+ + + + + +
+

40. Meaningless normative paragraph in examples

+

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.

+ + + + + +
+

41. Ios_base needs clear(), exceptions()

+

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).]

+ + + + + + + +
+

42. String ctors specify wrong default allocator

+

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. +]

+ + + + + + +
+

44. Iostreams use operator== on int_type values

+

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:

+
    +
  1. + In lib.basic.ios.members paragraph 13 (postcondition clause for + 'fill(cT)') change + +
         fillch == fill()
    +
    + + to + +
         traits::eq(fillch, fill())
    +
    + + +
  2. +
  3. + In lib.istream.unformatted paragraph 7 (effects clause for + 'get(cT,streamsize,cT)'), third bullet, change + +
         c == delim for the next available input character c
    +
    + + to + +
         traits::eq(c, delim) for the next available input character c
    +
    + +
  4. +
  5. + In lib.istream.unformatted paragraph 12 (effects clause for + 'get(basic_streambuf<cT,Tr>&,cT)'), third bullet, change + +
         c == delim for the next available input character c
    +
    + + to + +
         traits::eq(c, delim) for the next available input character c
    +
    + +
  6. +
  7. + In lib.istream.unformatted paragraph 17 (effects clause for + 'getline(cT,streamsize,cT)'), second bullet, change + +
         c == delim for the next available input character c
    +
    + + to + +
         traits::eq(c, delim) for the next available input character c
    +  
    + +
  8. +
  9. + In lib.istream.unformatted paragraph 24 (effects clause for + 'ignore(int,int_type)'), second bullet, change + +
         c == delim for the next available input character c
    +
    + + to + +
         traits::eq_int_type(c, delim) for the next available input
    +     character c
    +
    + +
  10. +
  11. + In lib.istream.unformatted paragraph 25 (notes clause for + 'ignore(int,int_type)'), second bullet, change + +
         The last condition will never occur if delim == traits::eof()
    +
    + + to + +
         The last condition will never occur if
    +     traits::eq_int_type(delim, traits::eof()).
    +
    + +
  12. +
  13. + In lib.istream.sentry paragraph 6 (example implementation for the + sentry constructor) change + +
         while ((c = is.rdbuf()->snextc()) != traits::eof()) {
    +
    + + to + +
         while (!traits::eq_int_type(c = is.rdbuf()->snextc(), traits::eof())) {
    +
    + +
  14. +
+ +

List of changes to Chapter 21:

+ +
    +
  1. + In lib.string::find paragraph 1 (effects clause for find()), + second bullet, change + +
         at(xpos+I) == str.at(I) for all elements ...
    +
    + + to + +
         traits::eq(at(xpos+I), str.at(I)) for all elements ...
    +
    + +
  2. +
  3. + In lib.string::rfind paragraph 1 (effects clause for rfind()), + second bullet, change + +
         at(xpos+I) == str.at(I) for all elements ...
    +
    + + to + +
         traits::eq(at(xpos+I), str.at(I)) for all elements ...
    +
    + +
  4. +
  5. + In lib.string::find.first.of paragraph 1 (effects clause for + find_first_of()), second bullet, change + +
         at(xpos+I) == str.at(I) for all elements ...
    +
    + + to + +
         traits::eq(at(xpos+I), str.at(I)) for all elements ...
    +
    + +
  6. +
  7. + In lib.string::find.last.of paragraph 1 (effects clause for + find_last_of()), second bullet, change + +
         at(xpos+I) == str.at(I) for all elements ...
    +
    + + to + +
         traits::eq(at(xpos+I), str.at(I)) for all elements ...
    +
    + +
  8. +
  9. + In lib.string::find.first.not.of paragraph 1 (effects clause for + find_first_not_of()), second bullet, change + +
         at(xpos+I) == str.at(I) for all elements ...
    +
    + + to + +
         traits::eq(at(xpos+I), str.at(I)) for all elements ...
    +
    +
  10. + +
  11. + In lib.string::find.last.not.of paragraph 1 (effects clause for + find_last_not_of()), second bullet, change + +
         at(xpos+I) == str.at(I) for all elements ...
    +
    + + to + +
         traits::eq(at(xpos+I), str.at(I)) for all elements ...
    +
    +
  12. + +
  13. + In lib.string.ios paragraph 5 (effects clause for getline()), + second bullet, change + +
         c == delim for the next available input character c 
    +
    + + to + +
         traits::eq(c, delim) for the next available input character c 
    +
    +
  14. + +
+ +

Notes:

+ + + + + + + +
+

46. Minor Annex D errors

+

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;
+ + + + + +
+

47. Imbue() and getloc() Returns clauses swapped

+

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.

+ + + + + +
+

48. Use of non-existent exception constructor

+

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.

+
+ + + + + +
+

49. Underspecification of ios_base::sync_with_stdio

+

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.]

+ + + + + + +
+

50. Copy constructor and assignment operator of ios_base

+

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.

+ + + + + +
+

51. Requirement to not invalidate iterators missing

+

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"

+ + + + + +
+

52. Small I/O problems

+

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".

+ + + + + +
+

53. Basic_ios destructor unspecified

+

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".

+ + + + + +
+

54. Basic_streambuf's destructor

+

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.

+
+ + + + + +
+

55. Invalid stream position is undefined

+

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))"

+ + + + + +
+

56. Showmanyc's return type

+

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.

+ + + + + +
+

57. Mistake in char_traits

+

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..." .

+ + + + + +
+

59. Ambiguity in specification of gbump

+

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.

+ + + + + +
+

60. What is a formatted input function?

+

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.

+

Duplicate of: 162, 163, 166

+

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.

+ + + + + +
+

61. Ambiguity in iostreams exception policy

+

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.

+ + + + + +
+

62. Sync's return value

+

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". +

+ + + + + +
+

63. Exception-handling policy for unformatted output

+

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. +

+ + + + + +
+

64. Exception handling in basic_istream::operator>>(basic_streambuf*)

+

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.

+
+ + + + + +
+

66. Strstreambuf::setbuf

+

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.

+
+ + + + + +
+

68. Extractors for char* should store null at end

+

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. +

+ + + + + +
+

69. Must elements of a vector be contiguous?

+

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:

+ + + + + + + +
+

70. Uncaught_exception() missing throw() specification

+

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().

+ + + + +
+

71. Do_get_monthname synopsis missing argument

+

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;
+ + + + +
+

74. Garbled text for codecvt::do_max_length

+

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. +

+ + + + +
+

75. Contradiction in codecvt::length's argument types

+

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.

+
+ + + + +
+

76. Can a codecvt facet always convert one internal character at a time?

+

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. +

+ + + + + +
+

78. Typo: event_call_back

+

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".

+ + + + +
+

79. Inconsistent declaration of polar()

+

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); 
+ + + + + +
+

80. Global Operators of complex declared twice

+

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.

+ + + + +
+

83. String::npos vs. string::max_size()

+

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.

+ + + + +
+

86. String constructors don't describe exceptions

+

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.

+ + + + +
+

90. Incorrect description of operator >> for strings

+

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.

+
+ + + + + +
+

91. Description of operator>> and getline() for string<> might cause endless loop

+

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.

+ + + + + +
+

92. Incomplete Algorithm Requirements

+

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.]

+ + + + + + + + +
+

98. Input iterator requirements are badly written

+

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.

+ + + + + +
+

103. set::iterator is required to be modifiable, but this allows modification of keys

+

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.]

+ + + + + + +
+

106. Numeric library private members are implementation defined

+

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: +

+ + + + + + + +
+

108. Lifetime of exception::what() return unspecified

+

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(). +

+ + + + + +
+

109. Missing binders for non-const sequence elements

+

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.]

+ + + + + + + +
+

110. istreambuf_iterator::equal not const

+

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;
+
+ + + + + +
+

112. Minor typo in ostreambuf_iterator constructor

+

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.

+
+ + + + + +
+

114. Placement forms example in error twice

+

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));
+
+ + + + + +
+

115. Typo in strstream constructors

+

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.

+ + + + + +
+

117. basic_ostream uses nonexistent num_put member functions

+

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.)

+ + + + + +
+

118. basic_istream uses nonexistent num_get member functions

+

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.]

+ + + + + + +
+

119. Should virtual functions be allowed to strengthen the exception specification?

+

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".

+ + + + + +
+

120. Can an implementor add specializations?

+

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.

+ + + + + +
+

122. streambuf/wstreambuf description should not say they are specializations

+

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.

+ + + + + +
+

123. Should valarray helper arrays fill functions be const?

+

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.

+ + + + + +
+

124. ctype_byname<charT>::do_scan_is & do_scan_not return type should be const charT*

+

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*.

+ + + + + +
+

125. valarray<T>::operator!() return type is inconsistent

+

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>.

+ + + + +
+

126. typos in Effects clause of ctype::do_narrow()

+

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)) )
+ + + + + +
+

127. auto_ptr<> conversion issues

+

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.

+ +
+ + + + + +
+

129. Need error indication from seekp() and seekg()

+

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

+ + + + +
+

130. Return type of container::erase(iterator) differs for associative containers

+

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. +]

+ + + + + + + +
+

132. list::resize description uses random access iterators

+

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.]

+ + + + + + +
+

133. map missing get_allocator()

+

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;
+ + + + +
+

134. vector constructors over specified

+

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. +

+ + + + +
+

136. seekp, seekg setting wrong streams?

+

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.]

+ + + + + + +
+

137. Do use_facet and has_facet look in the global locale?

+

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.

+ + + + +
+

139. Optional sequence operation table description unclear

+

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.

+
+ + + + +
+

141. basic_string::find_last_of, find_last_not_of say pos instead of xpos

+

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();

+ + + + +
+

142. lexicographical_compare complexity wrong

+

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] +

+ + + + +
+

144. Deque constructor complexity wrong

+

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.

+
+ + + + +
+

146. complex<T> Inserter and Extractor need sentries

+

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.

+ + + + +
+

147. Library Intro refers to global functions that aren't global

+

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. +

+ + + + +
+

148. Functions in the example facet BoolNames should be const

+

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!"; }

+
+ + + + +
+

150. Find_first_of says integer instead of iterator

+

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) ...

+
+ + + + +
+

151. Can't currently clear() empty container

+

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

+
+ + + + +
+

152. Typo in scan_is() semantics

+

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...."

+ + + + + +
+

153. Typo in narrow() semantics

+

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.]

+ + + + + + +
+

154. Missing double specifier for do_get()

+

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.

+ + + + +
+

155. Typo in naming the class defining the class Init

+

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.

+ + + + +
+

156. Typo in imbue() description

+

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&".

+ + + + +
+

158. Underspecified semantics for setbuf()

+

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."

+ + + + +
+

159. Strange use of underflow()

+

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".

+ + + + +
+

160. Typo: Use of non-existing function exception()

+

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.]

+ + + + + + +
+

161. Typo: istream_iterator vs. istreambuf_iterator

+

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...

+
+ + + + + +
+

164. do_put() has apparently unused fill argument

+

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.

+ + + + +
+

165. xsputn(), pubsync() never called by basic_ostream members?

+

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:

+
    +
  1. state in a footnote that this means that xsputn() will never be + called by any ostream member and that this is intended.
  2. +
  3. relax the restriction and allow calling overflow() and xsputn(). + Of course, the problem with flush() has to be resolved in some way.
  4. +
+ + +

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.]

+ + + + + + +
+

167. Improper use of traits_type::length()

+

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:

+ +

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>

+ + + + + +
+

168. Typo: formatted vs. unformatted

+

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."

+
+ + + + +
+

169. Bad efficiency of overflow() mandated

+

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.

+
+ + + + +
+

170. Inconsistent definition of traits_type

+

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;
+
+ + + + +
+

171. Strange seekpos() semantics due to joint position

+

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.]

+ + + + + + +
+

172. Inconsistent types for basic_istream::ignore()

+

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.

+ + + + +
+

173. Inconsistent types for basic_filebuf::setbuf()

+

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.

+ + + + +
+

174. Typo: OFF_T vs. POS_T

+

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;"

+ + + + +
+

175. Ambiguity for basic_streambuf::pubseekpos() and a few other functions.

+

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().

+ + + + +
+

176. exceptions() in ios_base...?

+

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.

+ + + + +
+

179. Comparison of const_iterators to iterators doesn't work

+

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.) +

+ + + + +
+

181. make_pair() unintended behavior

+

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.

+ + + + +
+

182. Ambiguous references to size_t

+

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.]

+ + + + + + + +
+

183. I/O stream manipulators don't work for wide character streams

+

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.]

+ + + + + + +
+

184. numeric_limits<bool> wording problems

+

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.]

+ + + + + + +
+

185. Questionable use of term "inline"

+

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.]

+ + + + + + +
+

186. bitset::set() second parameter should be bool

+

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.

+ + + + + +
+

187. iter_swap underspecified

+

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.

+ + + + + +
+

189. setprecision() not specified correctly

+

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)".

+ + + + +
+

193. Heap operations description incorrect

+

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

+
+ + + + + +
+

195. Should basic_istream::sentry's constructor ever set eofbit?

+

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). +

+
+ + + + +
+

198. Validity of pointers and references unspecified after iterator destruction

+

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.

+ + + + + + +
+

199. What does allocate(0) return?

+

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. +

+ + + + +
+

200. Forward iterator requirements don't allow constant iterators

+

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.]

+ + + + + + + +
+

201. Numeric limits terminology wrong

+

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 fundamental arithmetic +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. +

+
+ + + + + + +
+

202. unique() effects unclear when predicate not an equivalence relation

+

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.

+ + + + + +
+

206. operator new(size_t, nothrow) may become unlinked to ordinary operator new if ordinary version replaced

+

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: +

+ +

+-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: +

+ +

+-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). +

+ + +
+ +
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. +]

+ + + + + + +
+

208. Unnecessary restriction on past-the-end iterators

+

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. +

+ + + + +
+

209. basic_string declarations inconsistent

+

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. +

+ + + + +
+

210. distance first and last confused

+

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.

+ + + + +
+

211. operator>>(istream&, string&) doesn't set failbit

+

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).

+
+ + + + +
+

212. Empty range behavior unclear for several algorithms

+

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.

+ + + + +
+

214. set::find() missing const overload

+

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.]

+ + + + + + +
+

217. Facets example (Classifying Japanese characters) contains errors

+

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;
+}
+ + + + +
+

220. ~ios_base() usage valid?

+

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.

+
+ + + + +
+

221. num_get<>::do_get stage 2 processing broken

+

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.

+ + + + + +
+

222. Are throw clauses necessary if a throw is already implied by the effects clause?

+

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.

+ + + + +
+

223. reverse algorithm should use iter_swap rather than swap

+

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. +

+ + + + +
+

224. clear() complexity for associative containers refers to undefined N

+

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.

+ + + + +
+

225. std:: algorithms use of other unqualified algorithms

+

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.

+ + + + + +
+

226. User supplied specializations or overloads of namespace std function templates

+

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.

+ + + + + +
+

227. std::swap() should require CopyConstructible or DefaultConstructible arguments

+

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)

+
+ + + + + +
+

228. Incorrect specification of "..._byname" facets

+

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.]

+ + + + + + + +
+

229. Unqualified references of other library entities

+

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.]

+ + + + + + + +
+

230. Assignable specified without also specifying CopyConstructible

+

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.

+ + + + +
+

231. Precision in iostream?

+

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.]

+ + + + + + + +
+

232. "depends" poorly defined in 17.4.3.1

+

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.]

+ + + + + + +
+

233. Insertion hints in associative containers

+

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.

+

Duplicate of: 192, 246

+

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: +

+ +

+ + + + + + + + + + + + + +
Associative container requirements
expression return typeassertion/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. iterator p is a hint pointing to where +the insert should start to search. t is inserted as close as possible +to the position just prior to p. + +logarithmic in general, but amortized constant if t is inserted right after + before p. +
+
+ + + + + + +
+

234. Typos in allocator definition

+

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".

+ + + + +
+

235. No specification of default ctor for reverse_iterator

+

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.]

+ + + + + + +
+

237. Undefined expression in complexity specification

+

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).

+ + + + +
+

238. Contradictory results of stringbuf initialization.

+

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.

+ + + + +
+

239. Complexity of unique() and/or unique_copy incorrect

+

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.

+ + + + + + +
+

240. Complexity of adjacent_find() is meaningless

+

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.]

+ + + + + + + +
+

241. Does unique_copy() require CopyConstructible and Assignable?

+

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. +]

+ + + + + + + + +
+

242. Side effects of function objects

+

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:

+ +
    +
  1. The fully-closed ("[]" as opposed to half-closed "[)" ranges + are intentional. we want to prevent side-effects from + invalidating the end iterators.
  2. + +
  3. That has the unintentional side-effect of prohibiting + modification of the end element as a side-effect. This could + conceivably be significant in some cases.
  4. + +
  5. The wording also prevents side-effects from modifying elements + of the output sequence. I can't imagine why anyone would want + to do this, but it is arguably a restriction that implementors + don't need to place on users.
  6. + +
  7. Lifting the restrictions imposed in #2 and #3 above is possible + and simple, but would require more verbiage.
  8. +
+ +

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.]

+ + + + + + + +
+

243. get and getline when sentry reports failure

+

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.

+ + + + +
+

247. vector, deque::insert complexity

+

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.

+ + + + + +
+

248. time_get fails to set eofbit

+

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.

+ + + + +
+

250. splicing invalidates iterators

+

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.

+ + + + +
+

251. basic_stringbuf missing allocator_type

+

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;
+
+ + + + +
+

252. missing casts/C-style casts used in iostreams

+

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).
+ + + + +
+

253. valarray helper functions are almost entirely useless

+

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.

+ + + + + +
+

254. Exception types in clause 19 are constructed from std::string

+

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: +

+
    +
  1. A program which is low on memory may end up throwing +std::bad_alloc instead of out_of_range because memory runs out while +constructing the exception object.
  2. +
  3. An obvious implementation which stores a std::string data member +may end up invoking terminate() during exception unwinding because the +exception object allocates memory (or rather fails to) as it is being +copied.
  4. +
+ +

+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. +]

+ + + + + + + +
+

256. typo in 27.4.4.2, p17: copy_event does not exist

+

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.

+ + + + +
+

258. Missing allocator requirement

+

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. +]

+ + + + + +
+

259. basic_string::operator[] and const correctness

+

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)". +

+ + + + +
+

260. Inconsistent return type of istream_iterator::operator++(int)

+

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 `&').

+ + + + +
+

261. Missing description of istream_iterator::operator!=

+

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).

+ + + + +
+

262. Bitmask operator ~ specified incorrectly

+

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)); }
+
+ + + + +
+

263. Severe restriction on basic_string reference counting

+

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(). +

+ + + + +
+

264. Associative container insert(i, j) complexity requirements are not feasible.

+

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. +

+ + + + +
+

265. std::pair::pair() effects overly restrictive

+

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.

+ + + + +
+

266. bad_exception::~bad_exception() missing Effects clause

+

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. +

+ + + + +
+

268. Typo in locale synopsis

+

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();
+
+ + + + +
+

270. Binary search requirements overly strict

+

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.

+ + + + + +
+

271. basic_iostream missing typedefs

+

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;
+
+ + + + +
+

272. Missing parentheses around subexpression

+

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). +

+ + + + +
+

273. Missing ios_base qualification on members of a dependent class

+

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.

+ + + + +
+

274. a missing/impossible allocator requirement

+

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.]

+ + + + + + + +
+

275. Wrong type in num_get::get() overloads

+

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;
+
+ + + + +
+

276. Assignable requirement for container value type overly strict

+

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.

+ + + + + +
+

278. What does iterator validity mean?

+

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.

+ + + + + +
+

280. Comparison of reverse_iterator to const reverse_iterator

+

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. +]

+ + + + + + + +
+

281. std::min() and max() requirements overly restrictive

+

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]). +

+ + + + +
+

282. What types does numpunct grouping refer to?

+

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.]

+ + + + + + +
+

283. std::replace() requirement incorrect/insufficient

+

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: +

+ +
    +
  1. +Use of EqualityComparable, which only puts requirements on a single +type, when in fact an equality operator is required between two +different types, typically either T and the iterator's value type +or between the value types of two different iterators. +
  2. +
  3. +Use of Assignable for T when in fact what was needed is Assignable +for the value_type of the iterator, and convertability from T to the +value_type of the iterator. Or for output iterators, the requirement +should be that T is writable to the iterator (output iterators do +not have value types). +
  4. +
+ +

+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). +

+ + + + + +
+

284. unportable example in 20.3.7, p6

+

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.]

+ + + + + + +
+

285. minor editorial errors in fstream ctors

+

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. +

+ + + + +
+

286. <cstdlib> requirements missing size_t typedef

+

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>.

+ + + + + +
+

288. <cerrno> requirements missing macro EILSEQ

+

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. +

+ + + + + +
+

291. Underspecification of set algorithms

+

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.

+ + + + + +
+

292. effects of a.copyfmt (a)

+

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... +

+ + + + +
+

294. User defined macros and standard headers

+

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]

+ + + + + + +
+

295. Is abs defined in <cmath>?

+

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.

+ + + + + +
+

297. const_mem_fun_t<>::argument_type should be const T*

+

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.

+ + + + + +
+

298. ::operator delete[] requirement incorrect/insufficient

+

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:

+ +
+ +

to

+ +

+-12- Default behavior: Calls operator +delete(ptr) +or operator delete(ptr, std::nothrow) respectively. +

+

and expunge paragraph 13.

+ + + + +
+

300. list::merge() specification incomplete

+

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.]

+ + + + + + + +
+

301. basic_string template ctor effects clause omits allocator argument

+

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)

+
+ + + + +
+

303. Bitset input operator underspecified

+

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:

+ +
+ + + +

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.

+ + + + + +
+

305. Default behavior of codecvt<wchar_t, char, mbstate_t>::length()

+

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".]

+ + + + + + + +
+

306. offsetof macro and non-POD types

+

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.]

+ + + + + + +
+

307. Lack of reference typedefs in container adaptors

+

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:

+ +
    +
  1. Modifying these paragraphs to say that vector<bool> + is an exception.
  2. +
  3. Removing the vector<bool> specialization.
  4. +
  5. Changing the return types of stack and priority_queue to use + reference typedef's.
  6. +
+ +

+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.]

+ + + + + + +
+

308. Table 82 mentions unrelated headers

+

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].]

+ + + + + + +
+

310. Is errno a macro?

+

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:

+ + +

[ + 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.]

+ + + + + + + +
+

311. Incorrect wording in basic_ostream class synopsis

+

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. +]

+ + + + + + + +
+

312. Table 27 is missing headers

+

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>.

+ + + + + +
+

315. Bad "range" in list::unique complexity

+

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). +

+ + + + +
+

316. Vague text in Table 69

+

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... +

+ + + + + +
+

317. Instantiation vs. specialization of facets

+

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.

+ + + + + + + +
+

318. Misleading comment in definition of numpunct_byname

+

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.

+ + + + +
+

319. Storage allocation wording confuses "Required behavior", "Requires"

+

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 ...

+
+ + + + + +
+

320. list::assign overspecified

+

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.]

+ + + + + + + +
+

321. Typo in num_get

+

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.

+ + + + + + +
+

322. iterator and const_iterator should have the same value type

+

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. +

+ + + + + +
+

324. Do output iterators have value types?

+

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.

+ + + + + +
+

325. Misleading text in moneypunct<>::do_grouping

+

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. +

+ + + + +
+

327. Typo in time_get facet in table 52

+

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.]

+ + + + + + +
+

328. Bad sprintf format modifier in money_put<>::do_put()

+

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

+ + + + +
+

329. vector capacity, reserve and reallocation

+

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.

+ + + + + +
+

331. bad declaration of destructor for ios_base::failure

+

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.

+ + + + + + + +
+

333. does endl imply synchronization with the device?

+

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.

+ + + + + + + +
+

334. map::operator[] specification forces inefficient implementation

+

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.

+ + + + + +
+

335. minor issue with char_traits, table 37

+

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
+
+ + + + + +
+

336. Clause 17 lack of references to deprecated headers

+

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":

+ + + + + + + + + +
+

337. replace_copy_if's template parameter should be InputIterator

+

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.

+ + + + + +
+

338. is whitespace allowed between `-' and a digit?

+

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.

+ + + + + +
+

339. definition of bitmask type restricted to clause 27

+

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.]

+ + + + + + + + + +
+

340. interpretation of has_facet<Facet>(loc)

+

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.

+ + + + + + +
+

341. Vector reallocation and swap

+

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:

+ +
    +
  1. All Iterators and references into both vectors are invalidated.
  2. +
  3. Iterators and references into either vector remain valid, and remain +pointing to the same element. Consequently iterators and references that +referred to one vector now refer to the other, and vice-versa.
  4. +
+ + +

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. +

+ + + + + +
+

345. type tm in <cwchar>

+

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.

+ + + + + +
+

346. Some iterator member functions should be const

+

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.]

+ + + + + + + +
+

347. locale::category and bitmask requirements

+

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.] +

+
+
+ + + + + +
+

349. Minor typographical error in ostream_iterator

+

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. +

+ + + + + +
+

352. missing fpos requirements

+

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.

+ + + + + +
+

354. Associative container lower/upper bound requirements

+

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.]

+ + + + + + + + +
+

355. Operational semantics for a.back()

+

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;"]

+ + + + + + + +
+

358. interpreting thousands_sep after a decimal_point

+

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.

+ + + + + + +
+

359. num_put<>::do_put (..., bool) undocumented

+

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. +

+ + + + +
+

360. locale mandates inefficient implementation

+

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.

+ + + + + +
+

362. bind1st/bind2nd type safety

+

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.

+ + + + + +
+

363. Missing exception specification in 27.4.2.1.1

+

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.

+ + + + + +
+

364. Inconsistent wording in 27.5.2.4.2

+

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.

+ + + + + +
+

365. Lack of const-qualification in clause 27

+

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.

+ + + + + + +
+

369. io stream objects and static ctors

+

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.

+ + + + + +
+

370. Minor error in basic_istream::get

+

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.

+ + + + +
+

371. Stability of multiset and multimap member functions

+

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.

+ + + + + + +
+

373. Are basic_istream and basic_ostream to use (exceptions()&badbit) != 0 ?

+

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.

+ + + + + +
+

375. basic_ios should be ios_base in 27.7.1.3

+

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.

+ + + + +
+

376. basic_streambuf semantics

+

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.

+ + + + + +
+

379. nonsensical ctype::do_widen() requirement

+

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.

+ + + + + +
+

380. typos in codecvt tables 53 and 54

+

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." +

+ + + + +
+

381. detection of invalid mbstate_t in codecvt

+

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.

+ + + + + +
+

383. Bidirectional iterator assertion typo

+

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

+ + + + +
+

384. equal_range has unimplementable runtime complexity

+

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.

+ + + + +
+

386. Reverse iterator's operator[] has impossible return type

+

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. +]

+ + + + + + +
+

389. Const overload of valarray::operator[] returns by value

+

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.

+ + + + + +
+

391. non-member functions specified as const

+

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

+ + + + +
+

395. inconsistencies in the definitions of rand() and random_shuffle()

+

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.

+ + + + + +
+

400. redundant type cast in lib.allocator.members

+

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.

+ + + + +
+

401. incorrect type casts in table 32 in lib.allocator.requirements

+

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. +]

+ + + + + + + +
+

402. wrong new expression in [some_]allocator::construct

+

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. +

+ + + + + + + +
+

403. basic_string::swap should not throw exceptions

+

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. +

+ + + + + +
+

404. May a replacement allocation function be declared inline?

+

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. +

+ + + + + +
+

405. qsort and POD

+

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.]

+ + + + + + +
+

406. vector::insert(s) exception safety

+

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.]

+ + + + + + + +
+

407. Can singular iterators be destroyed?

+

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." +

+ + + + + +
+

409. Closing an fstream should clear error state

+

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.]

+ + + + + + + + +
+

410. Missing semantics for stack and queue comparison operators

+

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.

+ + + + + +
+

411. Wrong names of set member functions

+

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.

+ + + + + +
+

412. Typo in 27.4.4.3

+

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.]

+ + + + + + + +
+

413. Proposed resolution to LDR#64 still wrong

+

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. +

+ + + + + +
+

414. Which iterators are invalidated by v.erase()?

+

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.

+ + + + + +
+

415. behavior of std::ws

+

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]

+ + + + + + +
+

416. definitions of XXX_MIN and XXX_MAX macros in climits

+

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] +

+ + + + + +
+

420. is std::FILE a complete type?

+

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.

+ + + + + +
+

422. explicit specializations of member functions of class templates

+

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 +

+ +

+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.]

+ + + + + + +
+

425. return value of std::get_temporary_buffer

+

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]

+ + + + + +
+

426. search_n(), fill_n(), and generate_n() with negative n

+

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.

+ + + + + +
+

428. string::erase(iterator) validity

+

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.

+ + + + + +
+

432. stringbuf::overflow() makes only one write position available

+

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.

+ + + + + +
+

434. bitset::to_string() hard to use

+

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. +]

+ + + + + + + + +
+

435. bug in DR 25

+

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.]

+ + + + + + + +
+

436. are cv-qualified facet types valid facets?

+

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.]

+ + + + + + +
+

438. Ambiguity in the "do the right thing" clause

+

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: +

+ +
    +
  1. undefined behavior.
  2. +
  3. illegal and must be rejected.
  4. +
  5. legal and must be accepted.
  6. +
+ +

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:

+ + + +

In the previous paragraph the alternative binding will fail if f +is not implicitly convertible to X::size_type or if l is not implicitly +convertible to X::value_type.

+ +

+The extent to which an implementation determines that a type cannot be +an input iterator is unspecified, except that as a minimum integral +types shall not qualify as input iterators. +

+ + + +

[ +Kona: agreed that the current standard requires v('a', 'b') +to be accepted, and also agreed that this is surprising behavior. The +LWG considered several options, including something like +implicit_cast, which doesn't appear to be quite what we want. We +considered Howards three options: allow acceptance or rejection, +require rejection as a compile time error, and require acceptance. By +straw poll (1-6-1), we chose to require a compile time error. +Post-Kona: Howard provided wording. +]

+ + +

[ +Sydney: The LWG agreed with this general direction, but there was some +discomfort with the wording in the original proposed resolution. +Howard submitted new wording, and we will review this again in +Redmond. +]

+ + +

[Redmond: one very small change in wording: the first argument + is cast to size_t. This fixes the problem of something like + vector<vector<int> >(5, 5), where int is not + implicitly convertible to the value type.]

+ + + + +

Rationale:

+

The proposed resolution fixes:

+ +
  vector<int> v(10, 1);
+
+ +

+since as integral types 10 and 1 must be disqualified as input +iterators and therefore the (size,value) constructor is called (as +if).

+ +

The proposed resolution breaks:

+ +
  vector<vector<T> > v(10, 1);
+
+ +

+because the integral type 1 is not *implicitly* convertible to +vector<T>. The wording above requires a diagnostic.

+ +

+The proposed resolution leaves the behavior of the following code +unspecified. +

+ +
  struct A
+  {
+    operator int () const {return 10;}
+  };
+
+  struct B
+  {
+    B(A) {}
+  };
+
+  vector<B> v(A(), A());
+
+ +

+The implementation may or may not detect that A is not an input +iterator and employee the (size,value) constructor. Note though that +in the above example if the B(A) constructor is qualified explicit, +then the implementation must reject the constructor as A is no longer +implicitly convertible to B. +

+ + + + + +
+

441. Is fpos::state const?

+

Section: 27.4.3 [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. +

+ + + + + +
+

442. sentry::operator bool() inconsistent signature

+

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. +

+ + + + + +
+

443. filebuf::close() inconsistent use of EOF

+

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()). +

+ + + + + +
+

444. Bad use of casts in fstream

+

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). +

+ + + + + + + + +
+

445. iterator_traits::reference unspecified for some iterator categories

+

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. +]

+ + + + + + + + + +
+

448. Random Access Iterators over abstract classes

+

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&". +

+ + + + + +
+

449. Library Issue 306 Goes Too Far

+

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." +

+ + + + + +
+

453. basic_stringbuf::seekoff need not always fail for an empty stream

+

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. +

+ + + + + +
+

455. cerr::tie() and wcerr::tie() are overspecified

+

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.]

+ + + + + + +
+

456. Traditional C header files are overspecified

+

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 also placed 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] +

+
+ + + + + +
+

457. bitset constructor: incorrect number of initialized bits

+

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." +

+ + + + + +
+

460. Default modes missing from basic_fstream member specifications

+

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);
+
+ + + + + +
+

461. time_get hard or impossible to implement

+

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. +]

+ + + + + + + +
+

464. Suggestion for new member functions in standard containers

+

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

+
    +
  1. add vector<T>::data() member (const and non-const version) +semantics: if( empty() ) return 0; else return buffer_;
  2. +
  3. add map<Key,T>::at( const Key& k ) member (const and non-const version) +semantics: iterator i = find( k ); if( i != end() ) return *i; else throw range_error();
  4. +
+ +

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.

+ + + + + +
+

465. Contents of <ciso646>

+

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.]

+ + + + + + + +
+

467. char_traits::lt(), compare(), and memcmp()

+

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.]

+ + + + + + +
+

468. unexpected consequences of ios_base::operator void*()

+

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".]

+ + + + + + + + +
+

469. vector<bool> ill-formed relational operators

+

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]. +

+ + + + +
+

474. confusing Footnote 297

+

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. +

+ + + + +
+

475. May the function object passed to for_each modify the elements of the iterated sequence?

+

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.

+ + + + + +
+

478. Should forward iterator requirements table have a line for r->m?

+

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. +

+ + + + + +
+

488. rotate throws away useful information

+

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>
+    void ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
+                ForwardIterator last);
+
+ +

In 25.2.11 [alg.rotate], change:

+ +
  template<class ForwardIterator>
+    void ForwardIterator 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. +]

+ + + + + + + +
+

495. Clause 22 template parameter requirements

+

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.

+ + + + + +
+

496. Illegal use of "T" in vector<bool>

+

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".

+ + + + + +
+

497. meaning of numeric_limits::traps for floating point types

+

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.

+ + + + + +
+

505. Result_type in random distribution requirements

+

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_typeT---compile-time
+ +

[ +Berlin: Voted to WP. N1932 adopts the proposed resolution: see Table 5 row 1. +]

+ + + + + + + +
+

507. Missing requirement for variate_generator::operator()

+

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. +

+ + + + + +
+

508. Bad parameters for ranlux64_base_01

+

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: +

+
    +
  1. F. James, Comput. Phys. Commun. 60(1990) 329
  2. +
  3. G. Marsaglia and A. Zaman, Ann. Appl. Prob 1(1991) 462
  4. +
  5. M. Luscher, Comput. Phys. Commun. 79(1994) 100-110
  6. +
+ +

[ +Berlin: Voted to WP. N1932 adopts the proposed resolution in 26.3.5, +just above paragraph 5. +]

+ + + + + + + +
+

518. Are insert and erase stable for unordered_multiset and unordered_multimap?

+

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.

+
+ + + + + + +
+

519. Data() undocumented

+

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. +

+ + + + + +
+

520. Result_of and pointers to data members

+

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: +

+
    +
  1. If F is a member data pointer type R T::*, type +shall be cv R& when T1 is cv U1&, +R otherwise.
  2. +
+ +

[ +Peter provided wording. +]

+ + + + + + + +
+

521. Garbled requirements for argument_type in reference_wrapper

+

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: +

+ +
+ +
+ +

+Change bullet item 2 in 2.1.2/4: +

+ +
+ +
+ + + + + + +
+

524. regex named character classes and case-insensitivity don't mix

+

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. +]

+ + + + + +
+

527. tr1::bind has lost its Throws clause

+

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. +
+ + + + + + +
+

530. Must elements of a string be contiguous?

+

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. +

+ + + + + +
+

531. array forms of unformatted input functions

+

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. +]

+ + + + + + + +
+

533. typo in 2.2.3.10/1

+

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 *this p owns a deleter d... +

+ + + + + +
+

534. Missing basic_string members

+

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. +]

+ + + + + + +
+

535. std::string::swap specification poorly worded

+

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 were was in s, +s contains the same sequence of characters that +were was in *this. +

+
+ + + + + +
+

537. Typos in the signatures in 27.6.1.3/42-43 and 27.6.2.4

+

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);
+
+ + + + + +
+

538. 241 again: Does unique_copy() require CopyConstructible and Assignable?

+

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. +

+ + + + + +
+

540. shared_ptr<void>::operator*()

+

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. +

+ + + + + + +
+

541. shared_ptr template assignment and void

+

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;
+};
+
+ + + + + + +
+

542. shared_ptr observers

+

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] +

+ + + + + +
+

543. valarray slice default constructor

+

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: +

+
    +
  1. There are no elements to which the slice refers (i.e. undefined).
  2. +
  3. The slice specifies an array with no elements in it (i.e. defined).
  4. +
+

+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. +

+ + + + + + +
+

545. When is a deleter deleted?

+

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] +

+
+ + + + + +
+

550. What should the return type of pow(float,int) be?

+

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);
+
+
+ + + + + + +
+

551. <ccomplex>

+

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] +

+
+ + + + + + +
+

552. random_shuffle and its generator

+

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. +]

+ + + + + +
+

559. numeric_limits<const T>

+

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. +]

+ + + + + + + +
+

561. inserter overly generic

+

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, Iterator typename 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, Iterator typename 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, Inserter typename 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 +]

+ + + + + +
+

562. stringbuf ctor inefficient

+

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>& str,
+               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. If mode & 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. +]

+ + + + + +
+

563. stringbuf seeking from end

+

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 end high mark pointer minus the beginning +pointer (xend high_mark - xbeg). + +

+ + +

[ +Kona (2007) Moved to Ready. +]

+ + + + + +
+

566. array forms of unformatted input function undefined for zero-element arrays

+

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. + +

+
+ + + + + +
+

567. streambuf inserter and extractor should be unformatted

+

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 +]

+ + + + + +
+

574. DR 369 Contradicts Text

+

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 +]

+ + + + + +
+

575. the specification of ~shared_ptr is MT-unfriendly, makes implementation assumptions

+

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: +

+ +
+ +
+ +

+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] +

+ + + + + +
+

576. find_first_of is overconstrained

+

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<class ForwardIterator1InputIterator1, class ForwardIterator2>
+  ForwardIterator1InputIterator1
+  find_first_of(ForwardIterator1InputIterator1 first1, ForwardIterator1InputIterator1 last1,
+                        ForwardIterator2 first2, ForwardIterator2 last2);
+template<class ForwardIterator1InputIterator1, class ForwardIterator2,
+                  class BinaryPredicate>
+ForwardIterator1InputIterator1
+  find_first_of(ForwardIterator1InputIterator1 first1, ForwardIterator1InputIterator1 last1,
+                         ForwardIterator2 first2, ForwardIterator2 last2,
+                        BinaryPredicate pred);
+
+ + + + + + +
+

577. upper_bound(first, last, ...) cannot return last

+

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. +

+
+ + + + + + +
+

578. purpose of hint to allocator::allocate()

+

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 +allocate and not yet passed to member deallocate. +The value hint may be used by an implementation to help improve performance +223). [Note: The value hint may be used by an +implementation to help improve performance. -- end note] +

+

+[Footnote: 223)In a container member function, the address of an +adjacent element is often a good choice to pass for this argument. +

+ + + + +
+

581. flush() not unformatted function

+

Section: 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 +]

+ + + + + +
+

586. string inserter not a formatted function

+

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 typename basic_ostream<charT, +traits>::sentry k (os). If bool(k) is +true, Behaves as a formatted output function +(27.6.2.5.1). After constructing a sentry object, if +this object returns true when converted to a value of +type bool, determines padding as described in +22.2.2.2.2, 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(); 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. + +

+ + + + +
+

589. Requirements on iterators of member template functions of containers

+

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 of implicitly 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. +

+ + + + + +
+

593. __STDC_CONSTANT_MACROS

+

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] +

+ + + + + +
+

595. TR1/C++0x: fabs(complex<T>) redundant / wrongly specified

+

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 +]

+ + + + + +
+

596. 27.8.1.3 Table 112 omits "a+" and "a+b" modes

+

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 combinationstdio equivalent
binaryinouttruncapp 
    +     "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. +]

+ + + + + +
+

598. Decimal: Conversion to integral should truncate, not round.

+

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 type long long, as if performed by the expression llroundd32(*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 type long long, as if performed by the expression llroundd64(*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 type long long, as if performed by the expression llroundd64(*this) llroundd128(*this) while the decimal rounding direction mode [3.5.2] FE_DEC_TOWARD_ZERO is in effect. +

+ + + + + + +
+

599. Decimal: Say "octets" instead of "bytes."

+

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: +

+ +

+[Note: this implies that sizeof(std::decimal::decimal32) == 4, sizeof(std::decimal::decimal64) == 8, and sizeof(std::decimal::decimal128) == 16. --end note] +

+
+ + + + +
+

600. Decimal: Wrong parameters for wcstod* functions

+

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 char wchar_t * nptr, char wchar_t ** endptr);
+         decimal64  wcstod64  (const char wchar_t * nptr, char wchar_t ** endptr);
+         decimal128 wcstod128 (const char wchar_t * nptr, char wchar_t ** endptr);
+       }
+       }
+
+ + + + +
+

601. Decimal: numeric_limits typos

+

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>: +

+
    +
  1. The static member max() returns DEC128_MIN, this should be DEC128_MAX.
  2. +
  3. The static member digits is assigned to 384, +this should be 34 (Probably mixed up with the +max. exponent for decimal::decimal64).
  4. +
+
+ + +

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       = 384 34;
+            /* ... */
+
+ + + + +
+

602. Decimal: "generic floating type" not defined.

+

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, and long double, which are +collectively described as the basic floating types. +

+ + + + +
+

603. Decimal: Trivially simplifying decimal classes.

+

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.
+
+
+ + + + +
+

604. Decimal: Storing a reference to a facet unsafe.

+

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: base std::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: base std::use_facet<std::num_put<charT, OutputIterator> >(baseloc).put(s, f, fill, val). +

+ +

[ +Redmond: We would prefer to rename "extended" to "decimal". +]

+ + + + + + +
+

605. Decimal: <decfloat.h> doesn't live here anymore.

+

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 types float, double, and long double. Their contents remain unchanged by this Technical Report. +

+

+Headers <cdecfloat> and <decfloat.h> define characteristics of the decimal floating-point types decimal32, decimal64, and decimal128. 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 types decimal32, decimal64, and decimal128. 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;
+
+ + + + + +
+

607. Concern about short seed vectors

+

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. +]

+ + + + + +
+

608. Unclear seed_seq construction details

+

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. +]

+ + + + + +
+

609. missing static const

+

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. +

+ + + + + +
+

610. Suggested non-normative note for C++0x

+

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"). +

+
+ + + + + +
+

611. Standard library templates and incomplete types

+

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: +

+

+[...] +

+ +
+ +

+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: +

+ +
+ +
+ + + + + + +
+

612. numeric_limits::is_modulo insufficiently defined

+

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: +

+ +
    +
  1. Doesn't define what that value received is.
  2. +
  3. Doesn't state the result is repeatable
  4. +
  5. Doesn't require that doing addition, subtraction and other +operations on all values is defined behaviour.
  6. +
+ +

[ +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). +

+ + + + + + +
+

613. max_digits10 missing from numeric_limits

+

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 epsilon are 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;
+  ...
+
+ + + + + + + +
+

616. missing 'typename' in ctype_byname

+

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;
+
+ + + + + +
+

618. valarray::cshift() effects on empty array

+

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. +]

+ + + + + +
+

619. Longjmp wording problem

+

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. +

+ + + + + +
+

620. valid uses of empty valarrays

+

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 +length until 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 semantics may be +useful. The length of an empty array can be increased after +initialization by means of the resize() member +function. + +

+
+ + + + + +
+

621. non-const copy assignment operators of helper arrays

+

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: +

+ +
    +
  1. Add the const qualifier to the return types of these functions.
  2. +
  3. Change the return type of all the functions to void to match +the signatures of all the other assignment operators these classes +define.
  4. +
  5. Prohibit the copy assignment of these classes by declaring the +copy assignment operators private (as is done and documented by +some implementations).
  6. +
+ + + +

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. +]

+ + + + + +
+

622. behavior of filebuf dtor and close on error

+

Section: 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. Calls close(). + +

+

+ +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 then close 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, +and seekpos) was overflow 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 function it closes the file ("as if" by calling +std::fclose(file)).334) If any of the calls +made by the functionto overflow +or, including std::fclose, +fails then close 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 to close(), +the exception is caught but not rethrown (see +17.4.4.9 [res.on.exception.handling]). + +

+
+ + + + + +
+

623. 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 and basic_filebuf::pubimbue +causes any instance of basic_ios::imbue or +basic_streambuf::imbue to be called. ... + +

+ + + + + +
+

624. valarray assignment and arrays of unequal length

+

Section: 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. +

+
+
+ + + + + +
+

628. Inconsistent definition of basic_regex constructor

+

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 <class ForwardIterator InputIterator>
+  basic_regex(ForwardIterator InputIterator first, ForwardIterator InputIterator last, 
+              flag_type f = regex_constants::ECMAScript);
+
+ + + + + + +
+

634. allocator.address() doesn't work for types overloading operator&

+

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. +]

+ + + + + + + +
+

638. deque end invalidation during erase

+

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. +
+ + + + +
+

640. 27.6.2.5.2 does not handle (unsigned) long long

+

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: +
+ + + + + +
+

643. Impossible "as if" clauses

+

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) +

+ + + + + + +
+

646. const incorrect match_result members

+

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]. +

+ + + + + +
+

650. regex_token_iterator and const correctness

+

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. +]

+ + + + + +
+

651. Missing preconditions for regex_token_iterator c'tors

+

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. +]

+ + + + + +
+

652. regex_iterator and const correctness

+

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. +]

+ + + + + +
+

654. Missing IO roundtrip for random number engines

+

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. +]

+ + + + + +
+

655. Signature of generate_canonical not useful

+

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. +]

+ + + + + +
+

660. Missing Bitwise Operations

+

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() returns x & y .

+
+
template <class T> struct bit_or : binary_function<T,T,T> {
+  T operator()(const T& x , const T& y ) const;
+};
+
+

operator() returns x | y .

+
+
template <class T> struct bit_xor : binary_function<T,T,T> {
+  T operator()(const T& x , const T& y ) const;
+};
+
+

operator() returns x ^ y .

+
+
+ + + + + +
+

661. New 27.6.1.2.2 changes make special extractions useless

+

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. +

+ +
    +
  1. +The corresponding as-if extractions in paragraph 2 and 3 will never +result in a change of the operator>> argument val, because the +contents of the local variable lval is in no case written into val. +Furtheron both fragments need a currently missing parentheses in the +beginning of the if-statement to be valid C++. +
  2. +
  3. I would like to ask whether the omission of a similar explicit +extraction of unsigned short and unsigned int in terms of long - +compared to their corresponding new insertions, as described in +27.6.2.6.2 [ostream.inserters.arithmetic], is a deliberate decision or +an +oversight. +
  4. +
+ + +

Proposed resolution:

+
    +
  1. +

    +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);
    +
    +
  2. +
  3. +--- +
  4. +
+ + +

[ +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. +]

+ + + + + +
+

664. do_unshift for codecvt<char, char, mbstate_t>

+

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. +

+
+ + + + + +
+

665. do_unshift return value

+

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. +

+
+ + + + + + +
+

666. moneypunct::do_curr_symbol()

+

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 always typically +four characters long, usually three letters and a space. +

+
+ + + + + +
+

672. Swappable requirements need updating

+

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]
expressionreturn typepost-condition
swap(s,t)voidt 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]
expressionreturn typepost-condition
swap(s,t)voidt 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 MoveConstructible +requirements (Table 34 33) and the CopyAssignable MoveAssignable +requirements (Table 36 35); +
  • +
  • +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). +]

+ + + + + +
+

673. unique_ptr update

+

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. +

+ + + +

[ +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. +]

+ + + + + + + + + +
+

674. shared_ptr interface changes for consistency with N1856

+

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. +]

+ + + + + +
+

677. Weaknesses in seed_seq::randomize [rand.util.seedseq]

+

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 +

+ +
    +
  1. +

    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:

    + +
  2. +
  3. +

    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.

    +
  4. +
  5. seed_seq::randomize is undefined for v.size() == 0. The proposed + algorithm remedies this. +
  6. +
+

+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. +]

+ + + + + +
+

678. Changes for [rand.req.eng]

+

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: +

+ +
    +
  1. It replicates the functionality provided by X().
  2. +
  3. It leads to the possibility of a collision in the state provided + by some other X(q) with q.size() > 0.
  4. +
  5. It is inconsistent with the description of the X(q) in +paragraphs 26.4.3.1 [rand.eng.lcong] p5, 26.4.3.2 [rand.eng.mers] p8, and 26.4.3.3 [rand.eng.sub] p10 where +there is no special treatment of q.size() == 0.
  6. +
  7. The proposed replacement for seed_seq::randomize given above + allows for the case q.size() == 0.
  8. +
+ +

+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. +]

+ + + + + +
+

679. resize parameter by value

+

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);
+
+ + + + + + +
+

680. move_iterator operator-> return

+

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. +

+ +
    +
  1. pointer operator->() const {return &*current;}
  2. +
  3. typedef Iterator pointer;
  4. +
+ +

+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]: +

+ +
typedef typename iterator_traits<Iterator>::pointer pointer;
+
+ + + + + + +
+

681. Operator functions impossible to compare are defined in [re.submatch.op]

+

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. +]

+ + + + + +
+

682. basic_regex ctor takes InputIterator or ForwardIterator?

+

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. +]

+ + + + + +
+

685. reverse_iterator/move_iterator difference has invalid signatures

+

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_type auto 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_type auto 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_type auto 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_type auto 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. +]

+ + + + + + + +
+

687. shared_ptr conversion constructor not constrained

+

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 constructor The +second constructor shall not participate in the overload resolution +unless Y* shall be is 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: For tThe second and +third constructors, shall not participate in the +overload resolution unless Y* shall be +is implicitly convertible to T*. +

+
+ + + + + + +
+

689. reference_wrapper constructor overly constrained

+

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. +

+ + + + + +
+

693. std::bitset::all() missing

+

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:

+

+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. +

+
+
+ + + + + +
+

694. 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 in val. +M is the smaller of N and the +number of bits in the value representation (section [basic.types]) of +unsigned long long. If M < +N is true, 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 type unsigned long long. +
+
+Returns: x. +
+
+ + + + + +
+

695. ctype<char>::classic_table() not accessible

+

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;
+
+
+ + + + + +
+

699. N2111 changes min/max

+

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. +]

+ + + + + +
+

700. N1856 defines struct identity

+

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. +

+
+
+ +
+ + + + + + +
+

703. map::at() need a complexity specification

+

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. +

+
+ + + + + +
+

705. type-trait decay incompletely specified

+

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. +

+ + + + + + +
+

706. make_pair() should behave as make_tuple() wrt. reference_wrapper()

+

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>::type V1, typename decay<T2>::type V2> 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>::type V1,typename decay<T2>::type V2>(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. +

+
+ + + + + + +
+

710. Missing postconditions

+

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: +

+ +
+ +
+

+-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". +

+ + + + + + +
+

712. seed_seq::size no longer useful

+

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. +]

+ + + + + +
+

715. minmax_element complexity is too lax

+

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 is max_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 +corresponding comparisons predicate, where N is distance(first, last). +

+
+
+ + + + + + +
+

722. Missing [c.math] functions nanf and nanl

+

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. +

+ + + + + +
+

740. Please remove *_ptr<T[N]>

+

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]. +

+ + + + + + +
+

743. rvalue swap for shared_ptr

+

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);
+
+ + + + + +
+

744. What is the lifetime of an exception pointed to by an exception_ptr?

+

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] +
+ + + + + +
+

746. current_exception may fail with bad_alloc

+

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. +
+ + + + + +
+

749. Currently has_nothrow_copy_constructor<T>::value is true if T has 'a' nothrow copy constructor.

+

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 operator where 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 +a where all copy constructors that is are +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 takeing an lvalue of type T that is known not to +throw any exceptions or T is an array of such a class type. +
+
+ + + + + + +
+

755. std::vector and std:string lack explicit shrink-to-fit operations

+

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. +]

+ + + + + + +
+

759. A reference is not an object

+

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. +
+ + + + + + +
+

761. unordered_map needs an at() member function

+

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. +]

+ + + + + + + +
+

766. Inconsistent exception guarantees between ordered and unordered associative containers

+

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: +

+ +
+ +

+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: +

+ +
    +
  1. +erase(k) for associative containers is not allowed to throw. On +the other hand, erase(k) for unordered associative containers +is allowed to throw. +
  2. +
  3. +erase(q) for associative containers is not allowed to throw. On +the other hand, erase(q) for unordered associative containers +is allowed to throw if it uses the hash or predicate. +
  4. +
  5. +To fulfill 1), predicates of associative containers are not allowed to throw. +Predicates of unordered associative containers are allowed to throw. +
  6. +
  7. +2) breaks a widely used programming pattern (flyweight pattern) for +unordered containers, where objects are registered in a global map in +their constructors and unregistered in their destructors. If erase(q) is +allowed to throw, the destructor of the object would need to rethrow the +exception or swallow it, leaving the object registered. +
  8. +
+ + +

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. No erase(k) +function does not throws an 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: +

+ +
+ +
+ + + + + + +
+

768. Typos in [atomics]?

+

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; 
+};
+
+ + + + + + +
+

770. std::function should use rvalue swap

+

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);
+
+ + + + + + +
+

775. Tuple indexing should be unsigned?

+

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>
+  const Ptypename 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>
+  const Ptypename 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: 0 <= I and I < sizeof...(Types). The program is ill-formed if I is out of bounds. +

+

+2 Type: TI is the type of the Ith element of Types, where indexing is zero-based. +

+

+Update 20.4.1.5 [tuple.elem] Element access +

+
template <intsize_t I, class... types >
+typename tuple_element<I, tuple<Types...> >::type& get(tuple<Types...>& t);
+
+1 Requires: 0 <= I and I < sizeof...(Types). The program is ill-formed if I is out of bounds. +

+2 Returns: A reference to the Ith element of t, where indexing is zero-based. +

+Throws: Nothing. +
template <intsize_t I, class... types>
+typename tuple_element<I, tuple<Types...> >::type const& get(const tuple<Types...>& t);
+
+

+3 Requires: 0 <= I and I < sizeof...(Types). The program is ill-formed if I is out of bounds. +

+

+4 Returns: A const reference to the Ith 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: 0 <= I < N. The program is ill-formed if 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: 0 <= I < N. The program is ill-formed if I is out of bounds. +

+

+Returns: A reference to the Ith 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: 0 <= I < N. The program is ill-formed if I is out of bounds. +

+

+7 Returns: A const reference to the Ith 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. +]

+ + + + +
+

777. Atomics Library Issue

+

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;
+
+ + + + + + +
+

778. std::bitset does not have any constructor taking a string literal

+

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)). +

+
+ + + + + + +
+

781. std::complex should add missing C99 functions

+

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: +

+ +
    +
  1. +7.3.9.4: (required elements of the C99 library)
    +The cproj functions +
  2. +
  3. +7.26.1: (optional elements of the C99 library)
    +
    cerf    cerfc    cexp2
    +cexpm1  clog10   clog1p
    +clog2   clgamma  ctgamma
    +
    +
  4. +
+ +

+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 
+conj          polar proj
+imag          real
+
+
+ + + + + + +
+

782. Extended seed_seq constructor is useless

+

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:

+
    +
  1. +

    +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. +

    +
  2. + +
  3. +

    +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); +

    +
    +
    + +
  4. +
+ + + + + + +
+

783. thread::id reuse

+

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 a thread::id +that is not equal to the thread::id +of other threads of execution +and that is not equal to +the thread::id of std::thread objects +that do not represent threads of execution. +The library may reuse the value of a thread::id of a +terminated thread that can no longer be joined. +

+
+ + + + + +
+

789. xor_combine_engine(result_type) should be explicit

+

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. +

+ + + + + +
+

792. piecewise_constant_distribution is undefined for a range with just one endpoint

+

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, +
+ + + + + +
+

798. Refactoring of binders lead to interface breakage

+

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 fn op; 
+  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 fn op with x and value with y. +

+

+-2- operator() returns fnop(value,x). +

+
+
+ +

+Change D.8.3 [depr.lib.binder.2nd]: +

+ +
+
template <class Fn> 
+class binder2nd
+  : public unary_function<typename Fn::first_argument_type, 
+                          typename Fn::result_type> { 
+protected: 
+  Fn fn op; 
+  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 fn op with x and value with y. +

+

+-2- operator() returns fnop(value,x). +

+
+
+ + + + + + + \ No newline at end of file