Doc. no.        J16/98-0020
                    WG21/N1163
Date:            24 August 1998
Project:        Programming Language C++
Reply to:      Beman Dawes

Library Issues List

Reference ISO/IEC FDIS 14882:1998(E)

Also see Table of Contents and Index by Section

The purpose of this document is to serve as the committee's memory for Library Working Group (LWG) issues.

This document is in an experimental format designed for both viewing via a world-wide web browser and hard-copy printing.

It is the policy of the committee to accept any issue from a committee member which is well-formed, specific, and understandable, as determined by the issues list maintainer.   The issues list maintainer may edit an issue for brevity, grammar, or form.

Issues on this list should not to be confused with Defect Reports (DR's).  While some of the issues on this issues list will eventually be elevated to Defect Reports, other issues will be closed without action.  Defect Reports in turn may become the basis for Technical Corrigenda (TC's), or may be closed without action.

For background information, see lib-6565.


1.  C library linkage editing oversight

Section: 17.4.2.2 lib.using.linkage  Status: Open. Submitter: Beman Dawes  Date: 16 Nov 97

Due to an editing oversight, the change specified in the proposed resolution below did not make it into the Standard. This change had been accepted in principle at the London meeting, and the exact wording below was accepted at the Morristown meeting.

Proposed Resolution:

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


2.  auto_ptr conversions effects incorrect

Section: 20.4.5.3  lib.auto.ptr.conv   Status: Open. Submitter: Nathan Myers  Date: 4 Dec 97

Paragraph 1 in "Effects", says "Calls p->release()" where it clearly must be "Calls p.release()". (As it is, it seems to require using auto_ptr<>::operator-> to refer to X::release, assuming that exists.)

Proposed Resolution:

Change lib.auto.ptr.conv paragraph 1 Effects from "Calls p->release()" to "Calls p.release()".


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

Section: 18.3 lib.support.start.term  Status: Open. Submitter: Steve Clamage  Date: 12 Dec 97 Msg: lib-6500

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.

Proposed Resolution:

None yet


4.  basic_string size_type and difference_type should be implementation defined

Section: 21.3 lib.basic.string  Status: Open. Submitter: Beman Dawes  Date: 16 Nov 97

In Morristown we changed the size_type and difference_type typedefs for all the other containers to implementation defined with a reference to lib.container.requirements.   This should probably also have been done for strings.

Proposed Resolution:

Change lib.basic.string from:

typedef typename Allocator::size_type       size_type;
typedef typename Allocator::difference_type difference_type;

to:

typedef implementation defined size_type; // See lib.container.requirements
typedef implementation defined difference_type; // See lib.container.requirements

5.  string::compare specification questionable

Section: 21.3.6.8 lib.string::compare  Status: Open. Submitter: Jack Reeves   Date: 11 Dec 97

I was reviewing the latest version of the Draft (clause 21 - strings) when I came across what seems an obvious typo. I mention this because I am reasonably sure I pointed this out once before, and assumed it would get corrected. 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 I am forced to conclude that 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.

Like I said, I had assumed this was 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:


6.  file position not an offset unimplementable

Section: 27.4.3 lib.fpos  Status: Open. Submitter: Matt Austern  Date: 15 Dec 97

Table 88, in I/O, is too strict; it's unimplementable on systems where a file position isn't just an offset. It also never says just what fpos<> is really supposed to be. [Here's my summary, which Jerry agrees is more or less accurate. "I think I now know what the class really is, at this point: it's a magic cookie that encapsulates an mbstate_t and a file position (possibly represented as an fpos_t), it has syntactic support for pointer-like arithmetic, and implementors are encouraged but not required to have real, not just syntactic, support for arithmetic." This isn't standardese, of course.]

Later email from Matt: I'm told that Jerry does have standardese for the description of fpos<>.

Proposed Resolution:


7.  String clause minor problems

Section: 21 lib.strings  Status: Open. Submitter: Matt Austern  Date: 15 Dec 97

(1) In 21.3.5.4 lib.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 agument 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 lib.string::compare.

(6) In table 37, in section 21.1.1 lib.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:


8.  locale::global lacks guarantee

Section: 22.1.1.5 lib.locale.statics Status: Open. Submitter: Matt Austern   Date: 24 Dec 97

I think 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 note in 22.1.1.5 lib.locale.statics: "the library shall behave as if no other library function calls locale::global()."


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

Section: 18.4.1 lib.new.delete  Status: Open. Submitter: Steve Clamage  Date: 4 Jan 98

Scott Meyers:  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 inthe regard?

Steve: Yes, the FDIS is the same. I never noticed this change. Was it on purpose, or something that fell into an editorial crack?

Josee: The statement Scott refers to is still in Section 5.3.4, albeit a little bit modified. i.e. 5.3.4 para 7: "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.]"

Josee: Section 3.7.3.1 never discussed this, and the requirement has always been in Section 5.3.4 (or 5.3.3, as it was numbered in the ARM). Unfortunately, the last sentence in 5.3.4 para 7 is not normative. I believe this is a rule that should appear in Chapter 18, in the section on the C++ standard library operator new.

Josee: Section 3.7.3.1 describes the requirements on the semantics of the user provided new operators. The requirement that operator new(0) must return a pointer that is distinct from the pointer to any other object only holds, I believe, when the C++ standard library operator new is called. For other new operators, especially for class specific new operators, this requirement does not hold.

Josee: I think this is one of these core/library issues that the two WGs should discuss.

Proposed Resolution:


10.  codecvt<>::do unclear

Section: 22.2.1.5.2 lib.locale.codecvt.virtuals Status: Open. Submitter: Matt Austern   Date: 14 Jan 98

Section 22.2.1.5.2 says that codecvt<>::do_in and do_out should return the value noconv if "no conversion was needed". However, I don't see anything anywhere that defines what it means for a conversion to be needed or not needed. I can think of several circumstances where one might plausibly think that a conversion is not "needed", but I don't know which one is intended here.

Proposed Resolution:


11.  bitset minor problems

Section: 23.3.5 lib.template.bitset Status: Open. Submitter: Matt Austern   Date: 22 Jan 98

(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[]m 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.

(4) A library introduction issue. Is it a permitted extension for library implementors to add template parameters to standard library classes, provided that those extra parameters have defaults? For example, instead of defining template <class T, class Alloc = allocator<T> > class vector; defining it as template <class T, class Alloc = allocator<T>, int N = 1> class vector;

The standard may well already allow this (I can't think of any way that this extension could break a conforming program, considering that users are not permitted to forward-declare standard library components), but it ought to be explicitly permitted or forbidden.

Proposed Resolution:


12.  Way objects hold allocators unclear

Section: 20.1.5 lib.allocator.requirements  Status: Open. Submitter: Angelika Langer   Date: 23 Feb 98

I couldn't find a statement in the standard saying whether the allocator object held by a container is held as a copy of the constructor argument or whether a pointer of reference is maintained internal. There is an according statement for compare objects and how they are maintained by the associative containers, but I couldn't find anything regarding allocators.

Did I overlook it? Is it an open issue or known defect? Or is it deliberately left unspecified?

Proposed Resolution:


13.  eos refuses to die

Section: 27.6.1.2.3 lib.istream::extractors Status: Open. Submitter: William M. Miller   Date: 3 Mar 98

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 lib.istream::extractors, replace "eos" with "charT()"


14.  locale::combine should be const

Section: 22.1.1.3 lib.locale.members  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.locale] and also in 22.1.1.3 [lib.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 lib.locale.members  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.locale.members], paragraph 5, replace "locale(name())" with "locale(name().c_str())".


16.  bad ctype_byname<char> decl

Section: 22.2.1.4 lib.locale.ctype.byname.special  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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, [lib.facet.ctype.special].


17.  bad bool parsing

Section: 22.2.2.1.2 lib.facet.num.get.virtuals  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 examines the "boolalpha" flag wrongly. Finally, it doesn't define the value "loc".

In other words, the description is full of errors, and if the blatant errors are corrected, the result is unusable.

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();
  const string_type f = np.falsename();
  bool tm = true; bool 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) { err |= str.failbit; return in; }
  }
  val = tm;
  return in;

Notice this works when the candidate strings are both empty, and 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 [lib.facet.num.get.virtuals], 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. If a target sequence is uniquely matched, _val_ is set to the corresponding value; or if the targets are identical and matched, _val_ is set to _true_.

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 _val==true_ and _err==str.goodbit_. --end example]

Also: in the first line of paragraph 14, change "&&" to "&".


18.  get(...bool&) omitted

Section: 22.2.2.1.1 lib.facet.num.get.members  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.facet.num.get.members] another get member for bool&, copied from the entry in 22.2.2.1 [lib.locale.num.get].


19.  "noconv" definition too vague

Section: 22.2.1.5.2 lib.locale.codecvt.virtuals Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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.5.2 [lib.locale.codecvt.virtuals] to read:

noconv: input sequence is identical to converted sequence.

and change the Note in paragraph 2 to normative text as follows:

If returns _noconv_, the converted sequence is identical to the input sequence _[from,from_next)_._to_next_ is set equal to _to_, and the value of _state_ is unchanged.


20.  thousands_sep returns wrong type

Section: 22.2.3.1.2 lib.facet.numpunct.virtuals  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.facet.numpunct.virtuals], above paragraph 2, change "string_type" to "char_type".


21.  codecvt_byname<> instantiations

Section: 22.1.1.1.1 lib.locale.category  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.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.7 lib.ifstream.members  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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.7 [lib.ifstream.members], _and_ in 27.8.1.10 [lib.ofstream.members], under open(), one of

A. no change

B. Prepend to Effects: "If fail(), returns. Otherwise"...

C. Prepend to Effects: "Call clear(); then," ...


23.  num_get overflow result

Section: 22.2.2.1.2 lib.facet.num.get.virtuals  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

The current description of numeric input does not account for the possibility of overflow. This is an implicit result of changing the description to rely on the definition of scanf() (which fails to report overflow), and conflicts with the documented behavior of traditional and current implementations.

Users expect, when reading a character sequence that results in a value unrepresentable in the specified type, to have an error reported. The standard as written does not permit this.

Proposed Resolution:

In 22.2.2.1.2 [lib.facet.num.get.virtuals], paragraph 11, second bullet item, change

The sequence of chars accumulated in stage 2 would have caused scanf to report an input failure.

to

The sequence of chars accumulated in stage 2 would have caused scanf to report an input failure, or the value of the sequence cannot be represented in the type of _val_.


24.  "do_convert" doesn't exist

Section: 22.2.1.5.2 lib.locale.codecvt.virtuals  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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.5 [lib.locale.codecvt], paragraph 3, change "do_convert" to "do_in or do_out". Also, In 22.2.1.5.2 [lib.locale.codecvt.virtuals], change "do_convert()" to "do_in or do_out".


25.  string op>> uses width() value wrong

Section: 21.3.7.9 lib.string.io  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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:

In 21.3.7.9 [lib.string.io], paragraph 3, change the word "smaller" to "larger".


26.  Bad sentry example

Section: 27.6.1.1.2 lib.istream::sentry  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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:

Replace the example with better code, as follows:

  template <class charT, class traits = char_traits<charT> >
  basic_istream<charT,traits>::sentry(
           basic_istream<charT,traits>& is, bool noskipws = false) {
      ...
      typedef ctype<charT> ctype_type;
      const ctype_type& ct = use_facet<ctype_type>(is.getloc());
      for (int_type c = is.rdbuf()->sgetc();
           !traits::eq_int_type(c,traits::eof()) && ct.is(ctype.space,c);
           c = is.rdbuf()->snextc())
        {}
      ...
   }

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

Section: 21.3.5.5 lib.string::erase  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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.5.5 [lib.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 [lib.facet.ctype.char.membersStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.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 lib.narrow.stream.objects  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

Sections 27.3.1 and 27.3.2 [lib.wide.stream.objects] mention a function ios_base::init, which is not defined. Probably it means basic_ios<>::init, defined in 27.4.4.1 [lib.basic.ios.cons], paragraph 3.

Proposed Resolution:

In 27.3.1 [lib.narrow.stream.objects] paragraph 2, change

ios_base::init

to

basic_ios<char>::init

Also, make a similar change in 27.3.2 [lib.wide.stream.objects] except it should read

basic_ios<wchar_t>::init


30.  wrong header for LC_*

Section: 22.1.1.1.1 [lib.locale.categoryStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.locale.category], paragraph 2, change "<cctype>" to read "<clocale>".


31.  immutable locale values

Section: 22.1.1 [lib.localeStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.locale] paragraph 6, replace the text

"An instance of _locale_ is *immutable*;"

with

"A _locale_ value is *immutable*;"


32.  pbackfail description inconsistent

Section: 27.5.2.4.4 lib.streambuf.virt.pback  Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.streambuf.virt.pback], paragraph 1, change "*gptr()" to read instead "gptr()[-1]".


33.  codecvt<> mentions from_type

Section: 22.2.1.5.2 [lib.locale.codecvt.virtualsStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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.5.2 [lib.locale.codecvt.virtuals], paragraph 4, replace the definition in the table for the case of _error_ with

enountered a character in [from,from_end) that it could not convert.


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

Section: 22.2.2.2.2 [lib.facet.num.get.virtualsStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.facet.num.get.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 [lib.iostreams.baseStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

In 27.4.5.1, [lib.fmtflags.manip], we have a definition for a manipulator named "unitbuf". Unlike other manipulators, it's not listed in sysopsis. Similarly for "nounitbuf".

Proposed Resolution:

Add to the synopsis for <ios> in 27.4 [lib.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 [lib.ios.base.storageStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.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 [lib.localeStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.locale], paragraph 4, delete the parenthesized expression

(or, failing that, in the global locale)


38.  Facet definition incomplete

Section: 22.1.2 [lib.locale.global.templatesStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

Esa Pulkkinen has noticed 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 (not inherits) the public static member id as defined in (22.1.1.1.2, [lib.locale.facet]).


39.  sbufiter ++ definition garbled

Section: 24.5.3.4 [lib.istreambuf.iterator::op++Status: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.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 [lib.facets.examplesStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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 [lib.facets.examples] paragraph 3, 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 [lib.ios.baseStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

The description of ios_base::iword() and pword() in 27.4.2.4 [lib.ios.members.static], say that if they fail, they "set badbit, which may throw an exception". However, ios_base offers no interface to set or to test badbit; those interfaces are defined in basic_ios<>.

Proposed Resolution:

One of:

A. Move the definitions of basic_ios<> members clear, setstate, good, eof, fail, bad, and exceptions from basic_ios<> to ios_base. In particular, move them from the basic_ios<> synopsis 27.4.4 [lib.ios] and the definitions 27.4.4.3 [lib.iostate.flags] to the ios_base synopsis 27.4.2 [lib.ios.base] and definitions 27.4.2.1.2 [lib.ios::fmtflags] sections, respectively.

B. Change the description in 27.4.2.4 [lib.ios.members.static] 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 subobject of a basic_ios<> object or subobject, the failure may be detected by


42.  string ctors specify wrong default allocator

Section: 21.3 [lib.basic.stringStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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:

One of:

A. In 21.3 [lib.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 [lib.string.cons], 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 [lib.basic.string], and also in 21.3.1 [lib.string.cons], replace the declaration of the copy constructor as follows:

basic_string(const basic_string& str, size_type pos = 0,
             size_type n = npos); 

43.  Locale table correction

Section: 22.2.1.5.2 lib.locale.codecvt.virtuals  Status: Open. Submitter: Brendan Kehoe  Date: 1 Jun 98

It should have been changed after May '96, apparently.

Proposed Resolution:

Change 22.2.1.5.2 lib.locale.codecvt.virtuals table after paragraph 4 from:

	error     encountered a from_type character it could not convert

to:

	error     encountered a intern_type character it could not convert

44.  iostreams use operator== on int_type values

Section: 27 [lib.input.outputStatus: Open. Submitter: Nathan Myers  Date: 6 Aug 98

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:


45.  stringstreams read/write pointers initial position unclear

Section: lib.ostringstream  Status: Open. Submitter: Matthias Mueller  Date: 27 May 98

In a a comp.lang.c++.moderated Matthias Mueller wrote:

"We are not sure how to interpret the CD2 (see [lib.iostream.forward], [lib.ostringstream.cons], [lib.stringbuf.cons]) with respect to the question as to what the correct initial positions of the write and  read pointers of a stringstream should be."

"Is it the same to output two strings or to initialize the stringstream with the first and to output the second ?"

PJ Plauger, Bjarne Stroustrup, Randy Smithey, Sean Corfield, and Jerry Schwarz have all offered opinions; see reflector messages lib-6518, 6519, 6520, 6521, 6523, 6524.

Proposed Resolution:


46.  Minor Annex D errors

Section: D.7 depr.strstreambuf, depr.strstream Status: Open. Submitter: Brendan Kehoe  Date: 1 Jun 98

See lib-6522, 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 lib.ios.base.locales Status: Open. Submitter: Matt Austern  Date: 21 Jun 98

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 swap paragraphs 2 and 4.


48.  Use of non-existent exception constructor

Section: 27.4.2.1.1 lib.ios::failure  Status: Open. Submitter: Matt Austern  Date: 21 Jun 98

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:


49.  Underspecification of ios_base::sync_with_stdio

Section: 27.4.2.4 lib.ios.members.static Status: Open. Submitter: Matt Austern  Date: 21 Jun 98

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:


50.  Copy constructor and assignment operator of ios_base

Section: 27.4.2 lib.ios.base Status: Open. Submitter: Matt Austern  Date: 21 Jun 98

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 assingment operators unless you take specific steps to avoid them.) However, nothin 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). So I guess [remainder of comment disappeared into the black hole of email].

Proposed Resolution:


51.  Requirement to not invalidate iterators missing

Section: 23.1 lib.container.requirements  Status: Open. Submitter: David Vandevoorde  Date: 23 Jun 98

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 (lib-6528):

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.

Beman Dawes comments:

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"

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.


52.  Small I/O problems

Section: 27.4.3.2 lib.fpos.operations  Status: Open. Submitter: Matt Austern  Date: 23 Jun 98

First, 27.4.4.1 lib.basic.ios.cons table 89. This is pretty obvious: it should be titled "basic_ios<>() effects", not "ios_base() effects".

Second, 27.4.3.2 lib.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:


53.  basic_ios destructor unspecified

Section: 27.4.4 lib.ios  Status: Open. Submitter: Matt Austern  Date: 23 Jun 98

Matt:

There's nothing in 27.4.4 saying what basic_ios's destructor does. This is obviously another defect in clause 27.

The important question is whether basic_ios::~basic_ios() destroys rdbuf(). Do you happen to remember what the intention of the I/O working group was?

Nathan:

It absolutely should not delete rdbuf(). That's frequently a pointer to a member of a derived class, a member that has already been destroyed. Hence, it also shouldn't call rdbuf()->flush. Angelika Langer brought up these issues before.

Do you see anything else for ~basic_ios<>() to do? Certainly call the ios_base dtor, which plenty of work to do. But what has to happen in basic_ios<>?

Matt:

P.S. Another problem, one that's much less important, though, is what should happen when you call ios.rdbuf(0). In analogy with init() I suspect that ios ought to set badbit, but the standard (27.4.4.2, paragraph 6) doesn't say so.

Nathan:

I don't think it should set badbit. You might call it again with a non-null value, and then it wouldn't clear badbit. Various operations are specified to check if rdbuf() yields zero and set badbit, which would be unnecessary if were it already set by rdbuf.

Proposed Resolution:


54.  basic_streambuf's destructor

Section: 27.5.2  lib.streambuf Status: Open. Submitter: Matt Austern   Date:25 Jun 98

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 text saying that basic_streambuf's destructor has no effect


55.  invalid stream position is undefined

Section: 27  lib.input.output Status: Open. Submitter: Matt Austern   Date:26 Jun 98

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.

Proposed Resolution:

Everywhere that the phrase "invalid stream position" appears, replace it with pos_type(1).


56.  showmanyc's return type

Section: 27.5.2  lib.streambuf Status: Open. Submitter: Matt Austern   Date:29 Jun 98

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 class summary to streamsize.


57.  Mistake in char_traits

Section: 21.1.3.2  lib.char.traits.specializations.wchar.t Status: Open. Submitter: Matt Austern   Date:1 Jul 98

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


58.  Extracting a char from a wide-oriented stream

Section: 27.6.1.2.3  lib.istream::extractors  Status: Open. Submitter: Matt Austern   Date:1 Jul 98

27.6.1.2.3 has member functions for extraction of signed char and unsigned char, both singly and as strings. However, it doesn't say what it means to extract a char from a basic_streambuf<charT, Traits>.

basic_streambuf, after all, has no members to extract a char, so basic_istream must somehow convert from charT to signed char or unsigned char. The standard doesn't say how it is to perform that conversion.

Proposed Resolution:

operator>> should use narrow to convert from charT to char.


59.  Ambiguity in specification of gbump

Section: 27.5.2.3.1  lib.streambuf.get.area Status: Open. Submitter: Matt Austern   Date:28 Jul 98

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.

Jerry reports that the AT&T implementation used the former interpretation.

Proposed Resolution:

Add language to clarify that gbump() is simply a pointer increment, and that any attempt to move the pointer outside the range [eback(), egptr()] results in undefined behavior.


60.  What is a formatted input function?

Section: 27.6.1.2.1  lib.istream.formatted.reqmts Status: Open. Submitter: Matt Austern   Date:3 Aug 98

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.

Proposed Resolution:


61.  Ambiguity in iostreams exception policy

Section: 27.6.1.3  lib.istream.unformatted Status: Open. Submitter: Matt Austern   Date:6 Aug 98

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:

Clarify that the phrase "thrown during input" refers only to exceptions thrown by streambuf's overridden virtuals, not exceptions thrown as part of istream's error-reporting mechanism.


62sync's return value

Section: 27.6.1.3  lib.istream.unformatted Status: Open. Submitter: Matt Austern   Date:6 Aug 98

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, paragraph 36, change "returns traits::eof()" to "returns -1".


63.  Exception-handling policy for unformatted output

Section: 27.6.2.6  lib.ostream.unformatted Status: Open. Submitter: Matt Austern   Date:11 Aug 98

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:

Add an exception-handling policy similar to the one in 27.6.2.5.1 lib.ostream.formatted.reqmts, paragraph 1. The omission seems to have been unintentional.


64.  Exception-handling policy for unformatted output

Section: 27.6.1.2.3  lib.istream::extractors Status: Open. Submitter: Matt Austern   Date:11 Aug 98

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:

After talking to Jerry and Nathan, I believe that this rewritten version expresses the intent of the I/O working group.

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.


65.  Underspecification of strstreambuf::seekoff

Section: D.7.1.3  depr.strstreambuf.virtuals Status: Open. Submitter: Matt Austern   Date:18 Aug 98

The standard says how this member function affects the current stream position. (gptr or pptr) However, it does not say how this member function affects the beginning and end of the get/put area.

This is an issue when seekoff is used to position the get pointer beyond the end of the current read area. (Which is legal. This is implicit in the definition of seekhigh in D.7.1, paragraph 4.)

Proposed Resolution:

None.


66.  strstreambuf::setbuf

Section: D.7.1.3  depr.strstreambuf.virtuals Status: Open. Submitter: Matt Austern   Date:18 Aug 98

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:

Change the effects clause to say that the effects are implementation defined, except that setbuf(0,0) has no effect.


67.  setw useless for strings

Section: 21.3.7.9 lib.string.io  Status: Open. Submitter: Steve Clamage  Date: 9 Jul 98

Michel Michaud wrote: What should be output by :

   string text("Hello");
   cout << '[' << setw(10) << right << text << ']';

Shouldn't it be:

   [     Hello]

James Kanze replied: Actually, according to the FDIS, the width of the field should be the minimum of width and the length of the string, so the output shouldn't have any padding. I think that this is a typo, however, and that what is wanted is the maximum of the two. (As written, setw is useless for strings. If that had been the intent, one wouldn't expect them to have mentioned using its value.)

It's worth pointing out that this is a recent correction anyway; IIRC, earlier versions of the draft forgot to mention formatting parameters what soever.

Proposed Resolution:

Change 21.3.7.9 lib.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(); ..."


68.  Extractors for char* should store null at end

Section: 27.6.1.2.3 lib.istream::extractors Status: Open. Submitter: Angelika Langer  Date: 14 Jul 98

Angelika Langer:  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?

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:


69.  Must elements of a vector be contiguous?

Section: 23.2.4 lib.vector  Status: Open. Submitter: Andrew Koenig  Date: 29 Jul 1998

[The following are extracts from library reflector messages.  See the indicated message for the full text.]

Andrew Koenig in lib-6564:

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)

Dag Bruck in lib-6573 suggests:

I have made my mind up on vector<T>. I think it would be a good idea to regard it as a simple data structure with compact object allocation.

Given the declarations

typedef .... T;
T* p;
vector<T>::iterator i;

the following should be well-defined for any valid i:

1. static_cast<T*>(i) is well-defined.
2. p++ == static_cast<T*>(i++) and likewise for --.

Nathan Myers in lib-6576 suggests:

       1. &*i is well-defined and has type T* (or T const* for a const_iterator).
       2. 1+&*i == &*(1+i).

James Kanze in lib-6577 suggests:

What's wrong with just saying that for all i < v.size(), &v[ 0 ]+i == &v[ i ] (where i is an integral type, and not an iterator)?

Proposed Resolution:


70.  uncaught_exception() missing throw() specification

Section: 18.6 lib.support.exception, 18.6.4 lib.uncaught Status: Open. Submitter: Steve Clamage  Date:

In article 3E04@pratique.fr, Valentin Bonnard  writes:

uncaught_exception() doesn't have a throw specification.

It is intentionnal ? 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 18.6 lib.support.exception and 18.6.4 lib.uncaught add "throw()" to uncaught_exception().


71.  do_get_monthname synopsis missing argument

Section: 22.2.5.1 [lib.locale.time.getStatus: Open. Submitter: Nathan Myers  Date: 13 Aug 98

The locale facet member time_get<>::do_get_monthname is described in 22.2.5.1.2 [lib.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 [lib.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;

72.  do_convert phantom member function

Section: 22.2.1.5 lib.locale.codecvt  Status: Open. Submitter: Nathan Myers  Date: 24 Aug 98

In 22.2.1.5 par 3 lib.locale.codecvt, and in 22.2.1.5.2 par 8 lib.locale.codecvt.virtuals, a nonexistent member function "do_convert" is mentioned. This member was replaced with "do_in" and "do_out", the proper referents in the contexts above.

Proposed Resolution:

[The project editor requests the resolution include the actual replacement text.]


----- End of document -----