ISO/ IEC JTC1/SC22/WG21 N0795

-----------------------------------------------------------------
 
Updated Issues List for Library
X3J16/95-0195
WG21/N0795
P.J. Plauger
24 September 1995
 
 
-------- Clause 17 Issues -------
 
17.3.1.3:
A freestanding implementation doesn't include <stdexcept>,
which defines class exception, needed by <exception>.
Should probably move class exception to <exception>.
 
17.3.3.1:
A C++ program must be allowed to extend the namespace std if only
to specialize class numeric_limits.
 
17.3.4.1:
Paragraph 4 is a repeat.
 
 
-------- Clause 18 Issues -------
 
18.2.1:
float_rounds_style should be float_round_style (correct once).
 
18.2.1.1:
Paragraph 2 is subsumed by the descriptions of radix, epsilon(),
and round_error(). Should be removed here.
 
18.2.1.1:
Paragraph 3 is repeated as 18.2.1.2, paragraph 50, where it belongs.
Should be removed here.
 
18.2.1.1:
Should say that numeric_limits<T> must be able to return T(0).
Should say that round_style defaults to round_indeterminate,
not round_toward_zero.
 
18.2.1.2:
denorm_min() does *not* return the minimum positive normalized value.
Should strike the mention of this function in paragraph 2.
 
18.2.1.2:
Paragraph 22 must supply a more precise definition of ``rounding error.''
 
18.2.1.2:
Paragraph 23 must replace ``is in range'' with
``is a normalized value''.
 
18.2.1.2:
Paragraph 25 must replace ``is in range'' with
``is a normalized value''.
 
18.2.1.2:
Paragraph 27 must replace ``is in range'' with
``is a finite value''.
 
18.2.1.2:
Paragraph 29 must replace ``is in range'' with
``is a finite value''.
 
18.2.1.2:
In paragraph 41, ``flotaing'' should be ``floating''.
 
18.2.1.3:
Semantics must be specified for enum float_round_style.
 
18.5.1:
type_info::operator!=(const type_info&) is ambiguous
in the presence of the template operators in <utility>, and it is
unnecessary. It should be removed.
 
18.6.1.1:
Paragraph 1 incorrectly states that bad_exception is thrown by the
implementation to report a violation of an exception-specification.
Such a throw is merely a permissible option.
 
18.7:
There are five Table 28s.
 
 
-------- Clause 19 Issues -------
 
19.1.1:
exception(const exception&) should not be declared with the
return type exception&. (Error repeated in semantic description.)
 
 
-------- Clause 20 Issues -------
 
20.1:
Allocators are described in terms of ``memory models'' which is an
undefined concept in Standard C++. The term should be *defined* here
as the collection of related types, sizes, etc. in Table 33 that
characterize how to allocate, deallocate, and access objects of
some managed type.
 
20.1:
Paragraph 3 talks about ``amortized constant time'' for allocator
operations, but gives no hint about what parameter it should be
constant with respect to.
 
20.1:
a.max_size() is *not* ``the largest positive value of X::difference_type.''
It is the largest valid argument to a.allocate(n).
 
20.1:
Table 33 bears little resemblance to the currently accepted version
of class allocator (though it should, if various bugs are fixed, as
described later.) Essentially *every* item in the `expression' column
is wrong, as well as all the X:: references elsewhere in the table.
 
20.3:
binder1st is a struct in the synopsis, a class later.
Should be a class uniformly, like binder2nd.
 
20.3.5:
class unary_negate cannot return anything. Should say that its
operator() returns !pred(x).
 
20.3.6.1:
binder1st::value should have type Operation::first_argument_type,
not argument_type.
 
20.3.6.3:
binder2nd::value should have type Operation::second_argument_type,
not argument_type.
 
20.3.7:
``Shall'' is inappropriate in a footnote, within a comment, that
refers to multiple memory models not even recognized by the Standard.
 
20.4:
return_temporary_buffer shouldn't have a second (T*) parameter.
It's not in STL, it was not in the proposal to add it, and
it does nothing.
 
20.4.1:
allocator::types<T> shows all typedefs as private.
They must be declared public to be usable.
 
20.4.1:
It is not clear from Clause 14 whether explicit template member
class specializations can be first declared outside the containing
class. Hence, class allocator::types<void> should probably be declared
inside class allocator.
 
20.4.1:
The explicit specialization allocator::types<void> should include:
    typedef const void* const_pointer;
It is demonstrably needed from time to time.
 
20.4.1:
Footnote 169 should read ``An implementation,''
not ``In implementation.''
 
20.4.1.1:
allocator::allocate(size_type, types<U>::const_pointer) has no
semantics for the second (hint) parameter.
 
20.4.1.1:
allocator::allocate(size_type, types<U>::const_pointer) requires
that all existing calls of the form A::allocate(n) be rewritten
as al.allocate<value_type, char>(n, 0) -- a high notational
price to pay for rarely used flexibility. If the non-template form
of class allocator is retained, an unhinted form should
be supplied, so one can write al.allocate<value_type>(n).
 
20.4.1.1:
allocator::allocate(size_type, types<U>::const_pointer) should
return neither new T nor new T[n], both of which call the default
constructor for T one or more times. Note that deallocate, which
follows, calls operator delete(void *), which calls no destructors.
Should say it returns operator new((size_type)(n * sizeof (T))).
 
20.4.1.1:
allocator::max_size() has no semantics, and for good reason. For
allocator<T>, it knew to return (size_t)(-1) / sizeof (T) --
the largest sensible repetition count for an array of T. But the
class is no longer a template class, so there is no longer a T to
consult. Barring a general cleanup of class allocator, at the least
max_size() must be changed to a template function, callable as
either max_size<T>() or max_size(T *).
 
20.4.1.1:
A general cleanup of class allocator can be easily achieved by
making it a template class once again:
template<class T> class allocator {
public:
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;
    typedef T*        pointer;
    typedef const T*  const_pointer;
    typedef T&        reference;
    typedef const T&  const_reference;
    typedef T         value_type;
    pointer address(reference x) const;
    const_pointer address(const_reference x) const;
    pointer allocate(size_type n);
    void deallocate(pointer p);
    size_type init_page_size() const;
    size_type max_size() const;
    };
The default allocator object for a container of type T would then
be allocator<T>(). All of the capabilities added with the Nov. '94
changes would still be possible, and users could write replacement
allocators with a *much* cleaner interface.
 
20.4.1.2:
operator new(size_t N, allocator& a) can't possibly return
a.allocate<char, void>(N, 0). It would attempt to cast the
second parameter to allocator::types<void>::const_pointer,
which is undefined in the specialization allocator::types<void>.
If related problems aren't fixed, the second template argument
should be changed from void to char, at the very least.
 
20.4.1.2:
If allocator is made a template class once again, this version
of operator new becomes:
template<class T>
    void *operator new(size_t, allocator<T>& a);
 
20.4.1.3:
The example class runtime_allocator supplies a public member
allocate(size_t) obviously intended to mask the eponymous
function in the base class allocator. The signature must be
allocate<T, U>(size_t, types<U>::const_pointer) for that to
happen, however. The example illustrates how easy it is to
botch designing a replacement for class allocator, given its
current complex interface. (The example works as is with the
revised template class allocator described earlier.)
 
20.4.2:
raw_storage_iterator<OI, T>::operator*() doesn't return ``a reference
to the value to which the iterator points.'' It returns *this.
 
20.4.3.1:
Template function allocate doesn't say how it should ``obtain a
typed pointer to an uninitialized memory buffer of a given size.''
Should say that it calls operator new(size_t).
 
20.4.3.2:
Template function deallocate has no semantics. Should say that
it calls operator delete(buffer).
 
20.4.3.5:
get_temporary_buffer fails to make clear where it ``finds the largest
buffer not greater than ...'' Do two calls in a row ``find'' the same
buffer? Should say that the template function allocates the buffer
from an unspecified pool of storage (which may be the standard heap).
Should also say that the function can fail to allocate any storage
at all, in which case the `first' component of the return value is
a null pointer.
 
20.4.3.5:
Strike second parameter to return_temporary_buffer, as before.
Should say that a null pointer is valid and does nothing.
Should also say that the template function renders indeterminate
the value stored in p and makes the returned storage available
for future calls to get_temporary_buffer.
 
20.4.4:
Footnote 171 talks about ``huge pointers'' and type ``long long.''
Neither concept is defined in the Standard (nor should it be).
This and similar comments desperately need rewording.
 
20.4.4.3:
Header should be ``uninitialized_fill_n'', not ``uninitialized_fill.''
 
20.4.5:
When template class auto_ptr ``holds onto'' a pointer, is that the
same as storing its value in a member object? If not, what can it
possibly mean?
 
20.4.5:
auto_ptr(auto_ptr&) is supposed to be a template member function.
 
20.4.5:
auto_ptr(auto_ptr&) is supposed to be a template member function.
 
20.4.5:
auto_ptr<T>::operator= should return auto_ptr<T>&, not void, according
to the accepted proposal.
 
20.4.5.1:
Need to say that auto_ptr<T>::operator= returns *this.
 
20.4.5.2:
auto_ptr<T>::operator->() doesn't return get()->m -- there is no m.
Should probably say that ap->m returns get()->m, for an object ap
of class auto_ptr<T>.
 
20.4.5.2:
auto_ptr<T>::release() doesn't say what it returns. Should say
it returns the previous value of get().
 
20.4.5.2:
auto_ptr<T>::reset(X*) doesn't say what it returns, or that it deletes
its current pointer. Should say it executes ``delete get()'' and
returns its argument.
 
20.5:
The summary of <ctime> excludes the function clock() and the
types clock_t and time_t. Is this intentional?
 
 
-------- Clause 21 Issues -------
 
21.1:
template function operator+(const basic_string<T,tr,A> lhs,
   const_pointer rss) should have a second argument of type
const T *rhs.
 
21.1:
Paragraph 1 begins, ``In this subclause, we call...'' All first person
constructs should be removed.
 
21.1.1.1:
string_char_traits::ne is hardly needed, given the member eq.
It should be removed.
 
21.1.1.1:
string_char_traits::char_in is neither necessary nor sufficient.
It simply calls is.get(), but it insists on using the basic_istream
with the default ios_traits. operator>> for basic_string still has
to call is.putback(charT) directly, to put back the delimiter that
terminates the input sequence. char_in should be eliminated.
 
21.1.1.1:
string_char_traits::char_out isn't really necessary.
It simply calls os.put(), but it insists on using the basic_ostream
with the default ios_traits. char_out should be eliminated.
 
21.1.1.1:
string_char_traits::is_del has no provision for specifying a locale,
even though isspace, which it is supposed to call, is notoriously
locale dependent. is_del should be eliminated, and operator>> for
strings should stop on isspace, using the istream locale, as does
the null-terminated string extractor in basic_istream.
 
21.1.1.1:
string_char_traits is missing three important speed-up functions,
the generalizations of memchr, memmove, and memset. Nearly all the
mutator functions in basic_string can be expressed as calls to these
three primitives, to good advantage.
 
21.1.1.2:
No explanation is given for why the descriptions of the members of
template class string_char_traits are ``default definitions.''
If it is meant to suggest that the program can supply an explicit
specialization, provided the specialization satisfies the semantics
of the class, then the text should say so (here and several other
places as well).
 
21.1.1.2:
string_char_traits::eos should not be required to return the
result of the default constructor char_type() (when specialized).
Either the specific requirement should be relaxed or the function
should be eliminated.
 
21.1.1.2:
string_char_traits::char_in, if retained, should not be required to
return is >> a, since this skips arbitrary whitespace. The proper
return value is is.get().
 
21.1.1.2:
string_char_traits::is_del, if retained, needs to specify the locale
in effect when it calls isspace(a).
 
21.1.1.3:
Paragraph 1 doesn't say enough about the properties of a ``char-like
object.'' It should say that it doesn't need to be constructed or
destroyed (otherwise, the primitives in string_char_traits are
woefully inadequate). string_char_traits::assign (and copy) must
suffice either to copy or initialize a char_like element.
The definition should also say that an allocator must have the
same definitions for the types size_type, difference_type, pointer,
const_pointer, reference, and const_reference as class
allocator::types<charT> (again because string_char_traits has no
provision for funny address types).
 
21.1.1.4:
The copy constructor for basic_string should be replaced by two
constructors:
basic_string(const basic_string& str);
basic_string(const_basic_string& str, size_type pos,
   size_type n = npos, Allocator& = Allocator());
The copy constructor should copy the allocator object, unless
explicitly stated otherwise.
 
21.1.1.4:
basic_string(const charT*, size_type n, Allocator&) should be
required to throw length_error if n > max_size(). Should say:
Requires: s shall not be a null pointer
          n <= max_size()
Throws: length_error if n > max_size().
 
21.1.1.4:
basic_string(size_type n, charT, Allocator&) is required to throw
length_error if n == npos. Should say:
Requires: n <= max_size()
Throws: length_error if n > max_size().
21.1.16:
basic_string::size() Notes says the member function ``Uses
traits::length(). There is no reason for this degree of
overspecification. The comment should be struck.
 
21.1.1.6:
basic_string::resize should throw length_error for n >= max_size(),
not n == npos.
 
21.1.1.6:
resize(size_type) should not have a Returns clause -- it's a void
function. Clause should be labeled Effects.
 
21.1.1.6:
resize(size_type) should call resize(n, charT()), not
resize(n, eos()).
21.1.16:
basic_string::resize(size_type) Notes says the member function
``Uses traits::eos(). It should actually use charT() instead.
The comment should be struck.
 
21.1.1.6:
basic_string::reserve says in its Notes clause, ``It is guaranteed
that...'' A non-normative clause cannot make guarantees. Since the
guarantee is important, it should be labeled differently.
(This is one of many Notes clauses that make statements that should
be normative, throughout the description of basic_string.)
 
21.1.1.8.2:
basic_string::append(size_type n, charT c) should return
append(basic_string(n, c)). Arguments are reversed.
 
21.1.1.8.3:
basic_string::assign(size_type n, charT c) should return
assign(basic_string(n, c)). Arguments are reversed.
 
21.1.1.8.4:
basic_string::insert(size_type n, charT c) should return
insert(basic_string(n, c)). Arguments are reversed.
 
21.1.1.8.4:
basic_string::insert(iterator p, charT c) should not return p,
which may well be invalidated by the insertion. It should return
the new iterator that designates the inserted character.
 
21.1.1.8.4:
basic_string::insert(iterator, size_type, charT) should return
void, not iterator. (There is no Returns clause, luckily.)
 
21.1.1.8.5:
basic_string::remove(iterator) says it ``calls the character's
destructor'' for the removed character. This is pure fabrication,
since constructors and destructors are called nowhere else, for
elements of the controlled sequence, in the management of the
basic_string class. The words should be struck.
 
21.1.1.8.5:
basic_string::remove(iterator, iterator) says it ``calls the character's
destructor'' for the removed character(s). This is pure fabrication,
since constructors and destructors are called nowhere else, for
elements of the controlled sequence, in the management of the
basic_string class. The words should be struck.
 
21.1.1.8.5:
basic_string::remove(iterator, iterator) Complexity says ``the
destructor is called a number of times ...'' This is pure fabrication,
since constructors and destructors are called nowhere else, for
elements of the controlled sequence, in the management of the
basic_string class. The Complexity clause should be struck.
 
21.1.1.8.6:
replace(size_type pos1, size_type, const basic_string&,...) Effects
has the expression ``size() - &pos1.'' It should be ``size() - pos1.''
 
21.1.1.8.6:
basic_string::replace(size_type, size_type n, charT c) should return
replace(pos, n, basic_string(n, c)). Arguments are reversed.
 
21.1.1.8.8:
basic_string::swap Complexity says ``Constant time.'' It doesn't
say with respect to what. Should probably say, ``with respect to
the lengths of the two strings, assuming that their two allocator
objects compare equal.'' (This assumes added wording describing
how to compare two allocator objects for equality.)
 
21.1.1.9.1:
basic_string::find(const charT*, ...) Returns has a comma missing
before pos argument.
 
21.1.1.9.8:
basic_string::compare has nonsensical semantics. Unfortunately,
the last version approved, in July '94 Resolution 16, is also
nonsensical in a different way. The description should be
restored to the earlier version, which at least has the virtue
of capturing the intent of the original string class proposal:
1) If n is less than str.size() it is replaced by str.size().
2) Compare the smaller of n and size() - pos with traits::compare.
3) If that result is nonzero, return it.
4) Otherwise, return negative for size() - pos < n, zero for
size() - pos == n, or positive for size() - pos > n.
 
21.1.1.10.3:
operator!=(const basic_string&, const basic_string&) is ambiguous
in the presence of the template operators in <utility>, and it is
unnecessary. It should be removed.
 
21.1.1.10.5:
operator>(const basic_string&, const basic_string&) is ambiguous
in the presence of the template operators in <utility>, and it is
unnecessary. It should be removed.
 
21.1.1.10.6:
operator<=(const basic_string&, const basic_string&) is ambiguous
in the presence of the template operators in <utility>, and it is
unnecessary. It should be removed.
 
21.1.1.10.7:
operator>=(const basic_string&, const basic_string&) is ambiguous
in the presence of the template operators in <utility>, and it is
unnecessary. It should be removed.
 
21.1.1.10.7:
operator>= with const charT* rhs should return
lhs >= basic_string(rhs), not <=.
 
21.1.1.10.8:
Semantics of operator>> for basic_string are vacuous.
Should be modeled after those for earlier string class.
 
21.1.1.10.8:
Semantics of operator<< for basic_string are vacuous.
Should be modeled after those for earlier string class.
 
21.1.1.10.8:
getline for basic_string reflects none of the changes adopted by
July '94 resolution 26. It should not fail if a line exactly fills,
and it should set failbit if it *extracts* no characters, not if it
*appends* no characters. Should be changed to match 27.6.1.3.
 
21.1.1.10.8:
getline for basic_string says that extraction stops when npos - 1
characters are extracted. The proper value is str.max_size() (which
is less than allocator.max_size(), but shouldn't be constrained
more precisely than that). Should be changed.
 
21.2:
There are five Table 44s.
 
21.2:
<cstring> doesn't define size_type. Should be size_t.
 
 
-------- Clause 22 Issues -------
 
22.1:
template operator<<(basic_ostream, const locale&) as well as
template operator>>(basic_ostream, const locale&) now have a second
template argument (for ios traits) added without approval. While
this change may be a good idea, it should be applied uniformly (which
has not happened), and only after committee approval.
 
22.1:
The four template classes money_get, money_put, moneypunct,
and moneypunct_byname should all have a second template parameter
``bool International''.
 
22.1.1:
locale::category is defined as type unsigned. For compatibility with
C, it should be type int.
 
22.1.1:
Class locale is missing the constructor:
 locale(const locale& other, category) (Added Nov. '94).
It should be added.
 
22.1.1:
Class locale has the constructor locale::locale(const locale& other,
const locale& one, category). I can find no resolution that calls
for this constructor to be added.
 
22.1.1:
Example of use of num_put has silly arguments. First argument
should be ostreambuf_iterator(s.rdbuf()).
 
22.1.1:
Paragraph 8 says that locale::transparent() has unspecified behavior
when imbued on a stream or installed as the global locale. There is
no good reason why this should be so and several reasons why the
behavior should be clearly defined. The sentence should be struck.
 
22.1.1:
Paragraph 9 says that ``cach[e]ing results from calls to locale facet
member functions during calls to iostream inserters and extractors,
and in streambufs between calls to basic_streambuf::imbue, is
explicitly supported.'' In the case of inserters and extractors,
this behavior follows directly from paragraph 8. No need to say it
again. For basic_streambuf, the draft can (and should) say explicitly
that the stream buffer fixates on a facet at imbue time and ignores
any subsequent changes that might occur in the delivered facet
until the next imbue time (if then). (An adequate lifetime for the
facet can be assured by having the basic_streambuf object memorize
a copy of a locale object directly containing the facet,
as well as a pointer to the facet, for greater lookup speed.)
In any event, saying something ``is explicitly supported'' doesn't
make the behavior *required.* The paragraph should be struck, and
words added to the description of basic_streambuf to clarify the
lifetime of an imbued codecvt facet. (More words are needed here
anyway, for other reasons.)
 
22.1.1.1.1:
locale::category doesn't list the value none.
 
22.1.1.1.1:
Table 46 lists the ctype facets codecvt<char, wchar_t, mbstate_t>
and codecvt<wchar_t, char, mbstate_t> as being essential, but what
about codecvt<char, char, mbstate_t>? Should say that this facet
must be present and must cause no conversion.
 
22.1.1.1.1:
Table 46 omits the second (Intl) type parameter on all money_*
facets. The number of listed facets should thus double (one set
for false and the other for true.)
 
22.1.1.1.1:
Table 46, and paragraph 3 following, identify the facets that implement
each locale category (in the C library sense). But these words offer
no guidance as to what facets should be present in the default
locale (locale::classic()). The template classes listed each represent
an unbounded set of possible facets. Should list the following *31*
explicit instantiations of the templates as being required:
 collate<char>
 collate<wchar_t>
 ctype<char>
 ctype<wchar_t>
 codecvt<char, char, mbstate_t>
 codecvt<char, wchar_t, mbstate_t>
 codecvt<wchar_t, char, mbstate_t>
 moneypunct<char, false>
 moneypunct<wchar_t, false>
 moneypunct<char, true>
 moneypunct<wchar_t, true>
 money_get<char, false, istreambuf_iterator<char> >
 money_get<wchar_t, false, istreambuf_iterator<wchar_t> >
 money_put<char, false, ostreambuf_iterator<char> >
 money_put<wchar_t, false, ostreambuf_iterator<wchar_t> >
 money_get<char, true, istreambuf_iterator<char> >
 money_get<wchar_t, true, istreambuf_iterator<wchar_t> >
 money_put<char, true, ostreambuf_iterator<char> >
 money_put<wchar_t, true, ostreambuf_iterator<wchar_t> >
 num_get<char, istreambuf_iterator<char> >
 num_get<wchar_t, istreambuf_iterator<wchar_t> >
 num_put<char, ostreambuf_iterator<char> >
 num_put<wchar_t, ostreambuf_iterator<wchar_t> >
 numpunct<char>
 numpunct<wchar_t>
 time_get<char, istreambuf_iterator<char> >
 time_get<wchar_t, istreambuf_iterator<wchar_t> >
 time_put<char, ostreambuf_iterator<char> >
 time_put<wchar_t, ostreambuf_iterator<wchar_t> >
 messages<char>
 messages<wchar_t>
 
22.1.1.1.3:
Paragraph 1 of description of class locale::id is not a sentence.
Should read, ``The class locale::id provides ...'' (??)
 
22.1.1.2:
As mentioned earlier, locale::locale(const locale&, const locale&,
category) has been added without approval. It should be struck.
 
22.1.1.3:
Behavior of locale::use() is not defined if facet is present in
the locale. Should say it returns that facet.
 
22.1.1.3:
Description of locale::use() Effects contains a nonsense statement:
``Because locale objects are immutable, subsequent calls to use<Facet>()
return the same object, regardless of changes to the global locale.''
If a locale object is immutable, then changes to the global locale
should *always* shine through, for any facet that is not present
in the *this locale object. If the intent is to mandate cacheing
semantics, as sketched out in the original locales proposal, this
sentence doesn't quite succeed. Nor should it. Cacheing of facets
found in the global locale leads to horribly unpredictable behavior,
is unnecessary, and subverts practically any attempt to restore
compatibility with past C++ practice and the current C Standard.
The sentence should be struck.
 
22.1.1.3:
Description of locale::use Notes uses the term ``value semantics''
and the verb ``to last.'' Are either of these terms defined within
the Standard? The sentence should be reworded, or struck since it's
non-normative anyway.
 
22.1.1.3:
locale::use should not be required to return true after a locale::has
call for the same facet, for reasons described elsewhere. The sentence
should be struck.
 
22.1.1.4:
operator<<(basic_ostream, const locale&) has a nonsense definition,
since loc.name() cannot be inserted into an ostream with arbitrary
element type. Should be confined to work just with ostream, or
struck as needless frippery.
 
22.1.1.4:
operator>>(basic_istream, loc&) should have a second parameter of
type locale&. The Effects must also clarify what is meant by
``read a line'' and ``construct a locale from it.'' Should probably
say it calls getline(s, str) for some string str. If that succeeds
it then executes loc = locale(str.c_str()). But then how should it
convert from a non-char string to a char string? Should be confined
to work with just istream, or struck as needless frippery.
 
22.1.1.4:
operator>>(basic_istream, loc&) should specify how constructing a
locale can fail, if that is truly possible.
 
22.1.1.5:
locale::global has the clause ``Replaces ::setlocale().'' Does
this mean that a conforming implementation must *not* define
the function setlocale? Better to say that global behaves as if
it calls ::setlocale().
 
22.1.1.5:
locale::transparent() Notes says ``The effect of imbuing this locale
into an iostreams component is unspecified.'' If this is a normative
statement, it doesn't belong in a Notes clause. And if it's intended
to be normative, it should be struck. Imbuing a stream with
locale::transparent() is the *only* way to restore the behavior
of iostreams to that in effect for *every* C++ programming running
today. It is also essential in providing compatible behavior with
the C Standard. The sentence should be struck.
 
22.2.1.1:
ctype::narrow(charT, char) should return int, not char, to avoid
sign-extension problems. It should also have a default value for
dfault, such as '\0'.
 
22.2.1.1:
ctype::do_scan_is/do_scan_not should return const charT*,
not const char*.
 
22.2.1.1:
ctype::do_narrow(charT, char) should return int, not char, to avoid
sign-extension problems.
 
22.2.1.1.2:
ctype::do_is(ctype_mask, charT) Returns is already described under
Effects.
 
22.2.1.1.2:
ctype::do_is(const charT*, etc.) should return high.
 
22.2.1.1.2:
ctype::do_narrow does not have to require that digit have successive
codes. This is true of all character sets in C.
 
22.2.1.3:
ctype<char>::tolower/toupper/widen(char) should return int, not char,
to avoid sign-extension problems.
 
22.2.1.3:
ctype<char>::narrow(charT, char) should return int, not char, to avoid
sign-extension problems. It should also have a default value for
dfault, such as '\0'.
 
22.2.1.3:
ctype<char>::do_tolower/do_toupper(char) should return int, not char,
to avoid sign-extension problems.
 
22.2.1.3.2:
ctype<char> names table_, classic_table_ and delete_it_ have names
that suggest ``exposition only'' (with trailing underscores), are
sometimes shown as protected and other times shown as private, and
are grossly overspecified in the bargain. The ``classic table'', if
needed, can always be obtained from the "C" locale. It should not
be required in every ctype<char> object. The delete flag is of
interest only to the destructor and should not be exposed. The table
is of interest only to the is* functions, which have no virtuals
underneath. Hence, *none* of these objects should be part of the
external interface for the class.
 
22.2.1.3.2:
ctype<char>::do_is(const char*, etc.) should return high.
 
22.2.1.3.3:
ctype<char> describes this subclause as ``overridden virtual functions,''
but they're not. A template specialization has nothing to do with any
virtuals declared in the template. Should be renamed. (Should also
have some words added, since there are none.)
 
22.2.1.4:
Description of codecvt, paragraph 3, fails to make clear how an
implementation can ``provide instantiations for <char, wchar_t,
mbstate_t> and <wchar_t, char, mbstate_t>.'' Must specializations
be written for the template? If so, must they also have virtuals
that do the actual work? Or can the implementation add to the
default locale facets derived from the template, overriding the
virtual do_convert? Needs to be clarified.
 
22.2.1.4:
Implementations should also be required to provide an instantiation
of codecvt<char, char, mbstate_t> which transforms characters one
for one (preferably by returning noconv). It is needed for
the very common case, basic_filebuf<char>.
 
22.2.1.4.2:
codecvt::do_convert uses pointer triples (from, from_next, from_end)
and (to, to_next, to_end) where only pairs are needed. Since the
function ``always leaves the from_next and to_next pointers pointing
one beoond the last character successfully converted,'' the function
must be sure to copy from to from_next and to to to_next early on.
A better interface would eliminate the from and to pointers.
 
22.2.1.4.2:
codecvt::do_convert says ``If no translttion is needed (returns
noconv), sets to_next equal to argument to.'' The previous paragraph
strongly suggests that the function should also set from_next to
from. Presumably, the program will call do_convert once, with nothing
to convert. If it returns noconv, the program will omit future calls
to do_convert. If that is the intended usage, then it should be
permissible to call any instance of do_convert with (mostly)
null pointers, to simplify such enquiries -- and the wording should
make clear how to make such a test call.
If that is not the intended usage, then a result value should be
added that permits such a report, so adaptive programs can omit
future calls to convert that do nothing.
 
22.2.1.4.2:
codecvt::do_convert Notes says that the function ``Does not write
into *to_limit.'' Since there is no requirement that converted
characters be written into sequentially increasing locations
starting at to, this is largely toothless. Effects clause
should be written more precisely.
 
22.2.1.4.2:
codecvt::do_convert Returns says that the function returns partial
if it ``ran out of space in the destination.'' But the function
mbrtowc, for example, can consume the remaining source characters,
beyond the last delivered character, and absorb them into the
state. It would be a pity to require do_convert to undo this
work. Should say that partial can also mean the function ran out
of source characters partway through a conversion. Then
clarify that, after a return of partial, the
next call to do_convert should begin with any characters between
from_next and from_end, of which there might be none.
 
22.2.2:
Description of num_get and num_put say that ``implementations are
allowed to delegate extraction of smaller types to extractors for
larger types, but are not required to do so.'' This suggests that
a user replacement for num_get has to assume that get(long double)
might be called for *all* extractions. What if a program doesn't
want integers to have decimal points and exponents? Implementor
latitude should be more restricted.
 
22.2.2.1:
Template class num_get defines the type ios as basic_ios<charT>,
which it then uses widely to characterize parameters. Thus, this
facet can be used *only* with iostreams classes that use the
default traits ios_traits<charT>. Since the use of num_get is
mandated for *all* basic_istream classes, this restriction rules out
essentially any substitution of traits. Best fix is to make the
ios parameter an ios_base parameter on all the do_get calls,
then change ios accordingly. This is sufficient if
setstate is moved to ios_base as proposed elsewhere. But it requires
further fiddling for num_put if fill is moved *out* of ios_base,
as also proposed. Must be fixed, one way or another.
 
22.2.2.1.2:
num_get_do_get Effects says the functions can call str.setstate, which
may throw ios_base::failure. How is such an exception to be distinguished
from one thrown by a streambuf virtual? The latter must set badbit,
which might even throw another exception. Needs to be clarified.
 
22.2.2.1.2:
num_get_do_get Notes says ``if present, digit grouping is checked
after the entire number is read.'' Does this mean ``47,,,'' might
be consumed if comma is the thousands separator? Also says, ``When
reading a non-numeric boolean value, the names are compared exactly.''
What if the names are ``abc'' and ``abcde''? Which one wins if the
input is ``abcde''? What if the input is ``abcdx''? Desperately
needs clarifying.
 
22.2.2.2:
Template class num_put defines the type ios as basic_ios<charT>,
which it then uses widely to characterize parameters. Thus, this
facet can be used *only* with iostreams classes that use the
default traits ios_traits<charT>. Since the use of num_put is
mandated for *all* basic_ostream classes, this restriction rules out
essentially any substitution of traits. Best fix is to make the
ios parameter an ios_base parameter on all the do_put calls,
then change ios accordingly. This is sufficient if
setttate is moved to ios_base as proposed elsewhere. But it requires
further fiddling for num_put if fill is moved *out* of ios_base,
as also proposed. Must be fixed, one way or another.
 
22.2.3.1:
The syntax specified for numeric values is out of place in
numpunct.
 
22.2.3.1:
Description of numpunct says, ``For parsing, if the digits portion
contains no thousands-separators, no grouping constraint is applied.''
This suggests that thousands-separators are permitted in an input
sequence, and that the grouping constraint is applied, but it is
profoundly unclear on how this might be done. Allowing thousands-
separators at all in input is risky -- requiring that grouping
constraints be checked is an outrageous burden on implementors,
for a payoff of questionable utility and desirability. Should
remove any requirement for recognizing thoudands-separators and
grouping on input. And the effect on output needs considerable
clarification.
 
22.2.3.1.1:
Declaring vector<char> as the return type of numpunct::grouping
significantly adds to the number of header lines that must be
read for practically any program, yet produces little or no
payoff over string. Should be changed to string.
 
22.2.3.1.2:
numpunct::do_grouping has an encoding that differs arbitrarily from
that for C. It is also not as expressive as the C encoding. Should
return a string whose c_str() has the same meaning as in C.
 
22.2.4:
Template classes collate, time_get, time_put, money_get, money_put,
money_punct, messages, and their support classes still have only
sketchy semantics -- over a year after they were originally
accepted into the draft. They are based on little or no prior
art, and they present specification problems that can be addressed
properly only with detailed descriptions, which do not seem to be
forthcoming. Even if adequate wording were to magically appear
on short notice, the public still deserves the courtesy of a
proper review. For all these reasons, and more, the remainder
of clause 22 from this point on should be struck.
 
22.2.4.1.2:
collate::transform should be collate::do_transform.
 
22.2.4.1.2:
collate::hash should be collate::do_hash.
 
22.2.5.1:
time_get/put::ios should be changed from basic_ios<charT> to ios_base,
same as num_get and num_put.
 
22.2.5.1.2:
time_get::do_date_order refers to ``the date formst specified by
'X','' but that is a time format (e.g. 06:55:15) in strftime.
Should probably be 'x'. Presumably, it also refers to the behavior
of strftime when the global locale is set to match the locale for
which the time_get facet was created, but that is not stated.
 
22.2.5.3.2:
time_put::do_put should have a default last argument (modifier = 0).
 
22.2.5.3.2:
time_put::do_put talks about a format ``modifier, interpreted
identically as the format specifiers in the string argument to
the standard library function strftime().'' But that function
has no modifiers. Modifiers should be struck from put and do_put
functions.
 
22.2.6.1.2:
money_get::do_get talks about ``the format pattern'' used to specify
how to read characters, but fails to specify what that pattern might
be. It is hard to select between pos_format and neg_format when the
sign is one of the items to be read -- and the placement of the sign
is determined by the choice of format(!) Should either say that
pos_format is always used, or permit a more general input format.
 
22.2.6.1.2:
money_get::do_get talks says ``optional whitespace is consumed''
but fails to specify how whitespace is defined. Should probably
say that ctype<charT>.is(ctype_base::space, ch) returns true for
a whitespace character ch. (Should also use a similar recipe for
what constitutes a ``digit,'' but this is less important.)
 
22.2.6.3.1:
moneypunct::decimal_point and thousands_sep return charT, while
numpunct equivalents return strings. Should be reconciled.
 
22.2.7.1:
messages_base::THE_POSIX_CATALOG_IDENTIFIER_TYPE is not a defined type.
 
22.2.7.1:
The name `messages' differs from the C name `message' in a small
and arbitrary way that will lead to numerous errors in future.
Names should be reconciled.
 
22.2.7.1:
``typedef int catalog'' in template class messages hides type
catalog in messages_base. Probably should be struck.
 
22.2.7.1:
messages::open first argument is supposed to be `const char *'
not `const basic_string<char>&.' See March '95 Resolution #19.
 
22.2.7.1.2:
messages::do_get should at least specify a reliable way to get
the messages no and yes from the C locale. As it stands, it is
worthless in a portable program.
 
22.3:
Table 48 omits several LC_* macro names, for no apparent reason.
 
 
-------- Clause 23 Issues -------
 
23.1:
Table 50 should also list the required constructors X(al) and X(a, al),
for al an object of type Allocator.
 
23.1:
Copy constructors for all containers should copy the allocator.
A separate constructor, with a required allocator second argument,
should be added to permit the introduction of a new allocator
when copying a container. (Same is true for template class string.)
 
23.1.1:
Table 52 should make clear that a.insert(p, t) returns a pointer
to the newly inserted element.
 
23.1.1:
Table 53 should list a.at(n) for all containers that supply a[n]
(vector, deque).
 
23.1.2:
Table 54 lists a_uniq.insert(t) for functionality that is now merged
with a.insert(t).
 
23.1.2:
Table 54 should describe a.insert(t) much the same as a.insert(p, t),
with regard to inserting unique elements. It should also clarify that
``multi'' versions return iterator and non-multi versions return pair.
 
23.2.1:
The comments on the member functions operator~ and operator bool
of bitset::reference are erroneous.
 
23.2.1:
bitset::set(size_t pos, int val = 1) should be
bitset::set(size_t pos, bool val = true).
 
23.2.1:
bitset is missing:
 const bool operator[](size_t pos) const;
 reference at(size_t pos);
 bool at(size_t pos) const;
 
23.2.1.3:
bitset<N> operator& should return bitset(lhs) &= rhs, not &= pos.
 
23.2.1.3:
bitset<N> operator| should return bitset(lhs) |= rhs, not |= pos.
 
23.2.1.3:
bitset<N> operator^ should return bitset(lhs) ^= rhs, not ^= pos.
 
23.2.2:
deque::iterator and deque::const_iterator are incorrectly declared
in terms of Allocator types. They must be classes peculiar to deque.
 
23.2.3.1:
list::iterator and list::const_iterator are incorrectly declared
in terms of Allocator types. They must be classes peculiar to list.
 
23.2.3:
list::reverse_iterator and list::const_reverse_iterator should
be defined in terms of reverse_bidirectional_iterator, not
reverse_iterator.
 
23.2.3.7:
list::splice Effects should say ``The result is unchanged if...''
not ``The result is unchanged is ...''
 
23.2.3.7:
list::unique Effects doesn't say what happnns with binary_pred in the
template form. Should say that the predicate for removal is either
operator= or binary_pred.
 
23.2.3.7:
list::unique does not apply the binary predicate ``Exactly size() - 1''
times if size() is zero. Should qualify the statement for non-empty
lists only.
 
23.2.3.7:
list::merge doesn't state the ordering criteria for either version
of the two functions.
 
23.2.3.7:
list::merge doesn't state the ordering criteria for either version
of the two functions, at least not with sufficient completeness.
 
23.2.5.2:
Constructor vector() should be
 explicit vector(Allocator = allocator)
 
23.2.5.2:
Constructor `explicit vector(size_type, const T& = T())' should be
 explicit vector(size_type, const T& = T(), Allocator = allocator)
 
23.2.5.2:
Constructor `template<class II> vector(II, II)' should be
 template<class II> vector(II, II, Allocator = allocator)
 
23.2.5.4:
vector::resize should insert sz-s.size() elements, not s.size()-sz.
(I believe this text is replicated for all resize descriptions.)
 
23.2.5.6:
vector::insert template cannot meet the stated complexity requirements
(originally intended for a random_access_iterator) when the template
class parameter InputIterator is truly an input_iterator. They need
to be *carefully* rethought. (See 23.2.5.2 for the handling of
vector::vector template.)
 
23.2.6:
vector<bool, allocator>::const_reference should be bool,
not const reference.
 
23.2.6:
vector<bool>::reference should define operator=(const reference& x)
as returning ``*this = bool(x)''. The default assignment operator
is not adequate for this class.
 
23.3.1:
classes map, multimap, set, and multiset fail to define member types
iterator and const iterator properly. They are *not* synonyms for
Allocator::types<value_type>:: pointer, etc.
 
23.3.1:
map::operator[] return type should be Allocator::types<T>.reference,
not T&.
 
23.3.1:
map::operator[](const key_type&) const is an unapproved
(and nonsensical) addition. It should be struck.
 
23.3.1.1:
Much of the description of template classes map, multimap,
set, and multiset have no semantics. These must be supplied.
 
 
-------- Clause 24 Issues -------
 
24.1.6:
Class istreambuf_iterator should be declared with public base
class input_iterator. There is then no need to add a special
signature for iterator_category (which is missing from the
<iterator> synopsis).
 
24.1.6:
Template operator==(istreambuf_iterator) should not have
default template parameters.
 
24.1.6:
Template operator!=(istreambuf_iterator) is ambiguous in the
presence of template operator!=(const T&, const T&). It should
be struck.
 
24.1.6:
Class ostreambuf_iterator should be declared with public base
class output_iterator. There is then no need to list a special
signature for iterator_category.
 
24.1.6:
Template operator==(ostreambuf_iterator) and corresponding
operator!= are nonsensical and unused. They should be struck.
 
24.2.6:
Template function distance should have the requirement that last
is reachable from first by incrementing first.
 
24.3.1:
Paragraph 3 of description of reverse iterators has not been updated
to reflect the addition of the Reference template parameter.
 
24.3.1.1:
reverse_bidirectional_iterator::base and operator* should both
be const member functions.
 
24.3.1.2.1:
Effect of reverse_bidirectional_iterator() is not described.
 
24.3.1.2.5:
reverse_bidirectional_iterator::operator--() doesn't say what
it returns. Should say *this.
 
24.3.1.3:
reverse_iterator::base and operator* should both be const
member functions.
 
24.3.1.3:
reverse_iterator has no semantics for operators +, +=, -, -=, []
 
24.3.1.3:
reverse_iterator::operator[] should be a const member function.
 
24.3.1.3:
The four template operators defined for class reverse_iterator
should be declared outside the class.
 
24.3.1.3:
reverse_iterator has a Note that discusses
reverse_bidirectional_iterator, for some reason.
 
24.3.1.4.1:
reverse_iterator default constructor is not described.
 
24.3.1.4.5:
reverse_iterator::operator--() doesn't say what
it returns. Should say *this.
 
24.3.2.3:
Template class front_insert_iterator should not have a Returns clause.
 
24.3.2.5:
insert_iterator::operator++(int) returns a reference to *this,
unlike in other classes. Otherwise, the update of iter by
operator= gets lost.
 
24.3.2.6.5:
Declaration for template function inserter is missing second
template argument, class Iterator. It is also missing second
function argument, of type Iterator.
 
24.4.3:
istreambuf_iterator should have a member ``bool fail() const''
that returns true if any extractions from the controlled
basic_streambuf fail. This is desperately needed by istream
to restore its original approved functionality when these
iterators are used with facet num_get.
 
24.4.3.1:
istreambuf_iterator::proxy is not needed (once istreambuf_iterator
is corrected as described below). It should be removed.
 
24.4.3.2:
istreambuf_iterator(basic_istream s) should construct an
end-of-stream iterator if s.rdbuf() is null. Otherwise, it
should extract an element, as if by calling s->rdbuf()->sgetc(),
and save it for future delivery by operator*(). (Lazy input,
however, should be permitted.)
 
24.4.3.2:
istreambuf_iterator(basic_streambuf *) has no description
 
24.4.3.2:
istreambuf_iterator(const proxy&) should be removed.
 
24.4.3.3:
istreambuf_iterator::operator*() should deliver a stored
element, or call sgetc() on demand, then store the element.
It should *not* extract a character, since this violates the
input_iterator protocol.
 
24.4.3.4:
istreambuf_iterator::operator++() Effects should say that it
alters the stored element as if by calling s->snextc(), where
s is the stored basic_streambuf pointer.
 
24.4.3.4:
istreambuf_iterator::operator++(int) Effects should say that it
saves a copy of *this, then calls operator++(), then returns
the stored copy. Its return value should be istreambuf_iterator,
not proxy.
 
24.4.3.8:
template operator==(istreambuf_iterator&, istreambuf_iterator&)
should have const operands.
 
24.4.3.8:
template operator!=(istreambuf_iterator&, istreambuf_iterator&)
should have const operands. It also is ambiguous in the presence
of template<class T> operator!=(T, T) (as are many operators
in the library).
 
24.4.4:
ostreambuf_iterator::equal is silly, since output iterators
cannot in general be compared. It should be struck.
 
24.4.4:
ostreambuf_iterator should have a member ``bool fail() const''
that returns true if any insertions into the controlled
basic_streambuf fail. This is desperately needed by ostream
to restore its original approved functionality when these
iterators are used with facet num_put.
 
24.4.4.1:
ostreambuf_iterator::ostreambuf_iterator() produces a useless
object. It should be struck.
 
24.4.4.1:
ostreambuf_iterator;:ostreambuf_iterator(streambuf *) should
require that s be not null, or define behavior if it is.
 
24.4.4.2:
ostreambuf_iterator::equal is not needed and should be struck.
 
24.4.4.3:
ostreambuf_iterator::operator== is silly, since output iterators
cannot in general be compared. It should be struck.
 
24.4.4.3:
ostreambuf_iterator::operator!= is silly, since output iterators
cannot in general be compared. It should be struck.
 
 
-------- Clause 25 Issues -------
 
25:
adjacent_find should take/return forward iterators, not input iterators,
to return a truly useful value.
 
25:
Template function search(FI, FI, Size, T [, Pred]) is irreparably
ambiguous. Should be struck. (Similar versions have already been
struck without approval.)
 
25:
min/max_element should take/return forward iterators, not input
iterators, to return a truly useful value.
 
25.1.1:
for_each Notes: ``If f returns a result, the result is ignored.''
This is normative.
 
25.1.5:
adjacent find should probably work with forward iterators, not
input iterators. Otherwise, the return value is of only limited
usefulness. (You can dereference it, but you can't increment it.)
 
25.1.5:
adjacent_find Complexity refers to "value", whose meaning is left to
the reader's imagination.  Probably it means  *i , the value
at the returned iterator.
   Complexity:  Exactly  find(first, last, value) - first applications of
   the corresponding predicate.
And surely the value is off-by-one?  adjacent_find reports the first of
the two matching values, so if that match is equal to the first iterator,
then exactly 1 predicate has been performed?
 
25.1.9:
Paragraph 5: The second set of signatures for search
seems completely irreconcilable with the first set.
There's no way to avoid ambiguities: anything that would match
the four (or five) parameters of one would match the
four (or five) parameters of the other.
 
25.1.9:
search(FI, FI, Size, T [, Pred]) is hopelessly ambiguous. It should
be struck.
 
25.2.4:
replace_copy_if differs from replace_copy in some expected ways,
 but one difference is unexpected: first and last are just Iterators,
 instead of InputIterators. If this is intentional, add a note to
 explain why.
 
25.2.5:
fill should take output iterators, just like fill_n.
 
25.2.8:
unique should permit a worst-case complexity of last-first applications
of the predicate. The HP implementation calls adjacent_find, then
unique copy, to speed processing of lists with few or no duplicates.
To permit this useful optimization, one comparison must be repeated.
 
25.3.3:
Binary search: the discussion of non-random and random,
logarithmic or linear, is completely unclear.
 
25.3.3:
Binary search functions:
The description must certainly imply that the sequence is ordered
(increasing, according to the  operator<  or  comp  that is used)
but this should be stated explicitly.
Should the range of i be changed to: [first, last]? - Yes.
 
25.3.3.3:
The description of equal_range doesn't sound like the sequence
needs to be sorted, but it probably needs a clear statement
like all the others in this section.
 
25.3.7:
min_element and max_element should use forward iterators, not
input iterators. Otherwise, the return value is useless.
 
25.3.8:
lexocographical_compare:
According to lib-3934, the complexity limit should be ...
 Complexity: At most 2 * min((last1 - first1), (last2 - first2))  |
 applications of the corresponding comparison.
 
25.4:
Note for <cstdlib> says that the qsort function argument ``shall have
extern "C" linkage.'' I recall some discussion of this possibility,
but no resolution to that effect. Note also says that qsort ``is
allowed to propagate'' an exception, but evidently not required to
do so. In the same context, bsearch is mentioned, but it is not
given a similar constraint. Needs to be clarified.
 
 
-------- Clause 26 Issues -------
 
26.2:
operator!= with two complex operands is ambiguous in the presence
of template operator!=(T, T).
 
26.2:
operator== and operator!= for complex<T> should return bool,
not complex<T>.
 
26.2:
Complex functions acos, asin, atan, and atan2 are an unapproved
addition. All should be struck.
 
26.2:
Complex function log10 is an unapproved addition. It should be struck.
 
26.2:
Complex functions tan and tanh are an unapproved
addition. Both should be struck.
 
26.2:
The macro __STD_COMPLEX has been omitted from <complex>. This
is an unapproved change. It should be restored.
 
26.2.1:
The three constructors complex(), complex(T), and complex(T, T)
are later shown as complex(T = 0, T = 0). The latter notation
should also be used in the template definition.
 
26.2.1:
Template class complex needs to clarify what the constraints on
the type T for which it can be instantiated. It looks like you
must be able to perform arbitrary arithmetic mixed with floating-point
operands. It suggests that T() behaves like a numeric zero. But
nothing is said. Nor is it clear how an implementation is expected
to compute the hyperbolic cosine of an arbitrary type T. More
words are desperately needed here. The simplest reasonable constraint
is that T is a type that defines conversions to and from one of the
floating-point types -- double for best performance on average,
long double for maximum precision.
 
26.2.3:
The "template<class T>" shouldn't appear on the declaration:
 template<class T> complex(T re = T(), T im = T());
(Alternatively, the qualifier complex:: should be added, but this
departs from earlier style. Same comments apply for later members
in 26.2.4.
 
26.2.5:
complex operator != Returns is curdled. Should be !(lhs == rhs).
 
26.2.6:
Template arg(complex) Returns should say ``the phase angle of x,
or atan2(imag(x), real(x)).''
 
26.2.6:
Template conjg(complex) Returns should say ``the complex conjugage
of x, complex(real(x), -imag(x)).''
 
26.2.6:
template<class T> complex<T> polar(T rho, const t& theta);
What is  t  in  const t&? Should probably be T.
 
26.2.7:
complex acos, asin, atan, and atan2 are unapproved addition.
They should be struck.
 
26.2.7:
complex log10 is an unapproved addition. It should be struck.
 
26.2.7:
complex tan and tanh are unapproved addition.
They should be struck.
 
26.3:
Description of class slice should explain what ``BLAS-like'' means.
 
26.3:
valarray operator&& and operator|| overloads should probably all return
valarray<bool>, not valarray<T>.
 
26.3.1:
valarray::operator T*() and valarray::operator const T*() cause
numerous ambiguities. Should be omitted, or replaced by:
 T *begin();
 const T *begin() const;
 
26.3:
Paragraph 2 is unnecessary, since an implementation is permitted
to make *any* function inline. It should be struck.
 
26.3.1.1:
Much of valarray() Effects is non-normative commentary. Should
be moved to Notes.
 
26.3.1.1:
~valarray() has no stated semantics.
 
26.3.1.2:
First line: valarra<T>y should be valarray<T>.
 
26.3.1.2:
valarray::operator= has non-normative text in Effects:
``Assignment is the usual way to change the length of
an array after initialization.''
 
26.3.1.3:
Para 4. This sentence should be a non-normative note:
``This property indicates an absence of aliasing and may
be used to advantage by optimizing compilers.202)''
 
26.3.1.7:
valarray::operator T*() and valarray::operator const T*() cause
numerous ambiguities. Should be omitted, or replaced by:
 T *begin();
 const T *begin() const;
 
26.3.2.3:
Description of valarray::min/max is unclear on which of these
functions uses operator< and which operator>. The STL convention
is to require only operator< for both. The description should be
at least clarified, if not made simpler and more consistent.
 
26.3.4:
The behavior of valarray<T>::operator[](slice) is described
only in an example, which is non-normative.
 
26.3.5:
The behavior of valarray<T>::operator[](gslice) is described
only in an example, which is non-normative.
 
26.3.5.1:
Declarations of gslice constructors are duplicated.
 
26.3.8:
An indirect_array is produced by subscripting valarray with
a const valarray<size_t>, not a const valarray<int>. (See definition
of valarray.)
 
26.4.3:
Template function partial_sum does not ``assign to every iterator i...''
It ``assigns to *i for every iterator i...'' It also should clarify
that the first element of the sequence is simply *first.
 
26.5:
Table 64 omits tan and tanh for no apparent reason.
 
 
-------- Clause 27 Issues -------
 
27.1.1:
The definition of ``character'' is inadequate. It should say that it
is a type that doesn't need to be constructed or destroyed, and that
a bitwise copy of it preserves its value and semantics. It should
also say that it can't be any of the builtin types for which conflicting
inserters are defined in ostream or extractors are defined in istream.
 
27.1.2.4:
Description of type POS_T contains many awkward phrases. Needs rewriting
for clarity.
 
27.1.2.4:
Paragraph 2 has ``alg'' instead of ``all.''
 
27.1.2.4:
Footnote 207 should say ``for one of'' instead of ``for one if.''
Also, it should``whose representation has at least'' instead of
``whose representation at least.''
 
27.2:
Forward declarations for template classes basic_ios, basic_istream,
and basic_ostream should have two class parameters, not one. It
is equally dicey to define ios, istream, etc. by writing just one
parameter for the defining classes. All should have the second
parameter supplied, which suggests the need for a forward reference
to template class ios_char_traits as well, or at least the two usual
specializations of that class.
 
27.3:
<iostream> is required to include <fstream>, but it contains no overt
references to that header.
 
27.3.1:
cin.tie() returns &cout, not cout.
 
27.3.2:
win.tie() returns &cout, not cout.
 
27.4:
streamsize is shown as having type INT_T, but subclause 27.1.2.2
says this is the integer form of a character (such as int/wint_t).
streamsize really must be a synonym for int or long, to satisfy all
constraints imposed on it. (See Footnote 211.)
 
27.4:
Synopsis of <ios> is missing streampos and wstreampos. (They appear
in later detailed semantics.) Should be added.
 
27.4:
Synopsis of <ios> has the declaration:
 template <class charT> struct ios_traits<charT>;
The trailing <charT> should be struck.
 
27.4.1:
Type wstreamoff seems to have no specific use. It should be struck.
 
27.4.1:
Type wstreampos seems to have no specific use. It should be struck.
 
27.4.2:
ios_traits::state_type is listed as ``to be specified.''
It needs to be specified.
 
27.4.2:
Definition of ios_traits lists arguments backwards for is_whitespace.
Should have const ctype<char_type>& second, as in later description.
(Also, first argument should be int_type, as discussed in 27.4.2.3.)
 
27.4.2:
ios_traits description should make clear whether user specialization
is permitted. If it isn't, then various operations in <locale> and
string_char_traits are rather restrictive. If it is, then the draft
should be clear that ios_traits<char> and ios_traits<wchar_t> cannot
be displaced by a user definition.
 
27.4.2:
The draft now says ``an implementation shall provide'' instantiations
of ios_traits<char> and ios_traits<wchar_t>. It was changed without
approval from ``an implementation may provide.'' This change directly
contradicts Nov 94 Resolution 23. The proper wording should be
restored.
 
27.4.2.1:
ios_traits::state_type is defined in the wrong place. basic_streambuf
should be permitted to define this type, since it knows best what it
needs. Having it in ios_traits is close to useless.
 
27.4.2.2:
ios_traits::not_eof should take an argument of int_type, not char_type.
 
27.4.2.2:
ios_traits::not_eof says nothing about the use made of its argument c.
Should say that it returns c unless it can be mistaken for an eof().
 
27.4.2.2:
ios_traits::not_eof has two Returns clauses. The second is an
overspecificationaand shuuld be struck.
 
27.4.2.2:
ios_traits::length has an Effects clause but no Returns clause.
The Effects clause should be reworded as a Returns clause.
 
27.4.2.3:
First argument to is_whitespace has been changed from int_type to
char_type with no enabling resolution. It is also a bad idea.
Should be restored to int_type.
 
27.4.2.3:
is_whitespace supposedly behaves ``as if it returns ctype.isspace(c),''
but that function doesn't eiist. Should say ``as if it returns
ctype.is(ctype_base::space, c).'' Even better, the function should
be dropped, letting basic_istream call the obvious function directly.
 
27.4.2.3:
The draft now says that ios_traits functions to_char_type, to_int_type,
and copy are ``provided from the base struct
string_char_traits<CHAR-T>.'' This is a substantive change made
without approval. It is also nonsensical, since there is no such
``base struct.'' The wording should be struck.
 
27.4.2.4:
ios_traits::to_char_type has an Effects clause which should be
reworded as a Returns clause.
 
27.4.2.4:
ios_traits::to_int_type has an Effects clause which should be
reworded as a Returns clause.
 
27.4.2.4:
ios_traits::copy has an Effects clause which should be
reworded as a Returns clause. (It returns src.)
 
27.4.2.4:
ios_traits::get_state should be specified to do more than return zero.
Semantics are inadequate. A pos_type conceptually has three
components: an off_type (streamsize), an fpos_t, and a state_type
(mbstate_t, which may be part of fpos_t). It must be possible
to compose a pos_type from these elements, in various combinations,
and to decompose them into their three parts. As with state_type
(27.4.2.1), this doesn't belong in ios_traits. Should be removed,
along with get_pos.
 
27.4.2.4:
ios_traits::get_pos should be specified to do more than return
pos_type(pos). Semantics are inadequate. See comments on get_state.
above.
 
27.4.3:
ios_base::fill() cannot return int_type because it's not defined.
Should be int if fill() is left in ios_base.
 
27.4.3:
ios_base::precision() and width() should deal in streamsize
arguments and return values, not int. (Even more precisely,
they should be moved to basic_ios and have all their types
changed to traits::streamoff.)
 
27.4.3.1.6:
~Init() should call flush() for wout, werr, and wlog, not just for
cout, cerr, and clog.
 
27.4.3.2:
ios_baee::fill(int_type) cannot receive or return int_type
because it's not defined. Both should be int if fill(int_type)
is left in ios_base.
 
27.4.3.4:
ios_base::iword allocates an array of long, not of int.
 
27.4.3.4:
ios_base::iword Notes describes a normative limitation on the lifetime
of a returned reference. It should not be in a Notes clause. It should
also say that the reference becomes invalid after a copyfmt, or when
the ios_base object is destroyed.
 
27.4.3.4:
ios_base::pword Notes describes a normative limitation on the lifetime
of a returned reference. It should not be in a Notes clause. It should
also say that the reference becomes invalid after a copyfmt, or when
the ios_base object is destroyed.
 
27.4.3.5:
Protected constructor ios_base::ios_base() must *not* assign initial
values to its member objects as indicated in Table 72. That operation
must be deferred until basic_ios::init is called. Should say here
that it does no initialization, then move Table 72 to description of
basic_ios::init (27.4.4.1). Also should emphasize that the object
*must* be initialized before it is destroyed (thanks to reference
counting of locale objects).
 
27.4.3.5:
Table 72 shows result of rdstate() for a newly constructed
ios_base object, but that object defines no such member function.
(Will be fixed if table is moved to basic_ios, as proposed.)
 
27.4.4.1:
basic_ios::basic_ios() has next to no semantics. Needs to be
specified:
 fffects: Constructs an object of class basic_ios, leaving its
 member objects uninitialized. The object *must* be initialized
 by calling init(basic_streambuf *sb) before it is destroyed.
 
27.4.4.1:
basic_ios::init(basic_streambuf *sb) has no semantics.
Needs to be specified:
 Postconditions: rdbuf() == sb, tie() == 0, ios_base initialized
 according to Table 72 (currently in 27.4.3.5).
 
27.4.4.2:
basic_ios::tie is not necessarily synchronized with an *input*
sequence. Can also be used with an output sequence.
 
27.4.4.2:
basic_ios::imbue(const locale&) should call rdbuf()->pubimbue(loc)
only if rdbuf() is not a null pointer. Even better, it should not
call rdbuf()->pubimbue(loc) at all. Changing the locale that
controls stream conversions is best decoupled from changing
the locale that affects numeric formatting, etc. Anyone who knows
how to imbue a proper pair of codecvt facets in a streambuf won't
mind having to make an explicit call.
 
27.4.4.2:
basic_ios::imbue(const locale&) doesn't specify what value it returns.
Should say it returns whatever ios_base::imbue(loc) returns.
 
27.4.4.2:
basic_ios::copyfmt should say that both rdbuf() and rdstate() are
left unchanged, not just the latter.
 
27.5.2:
basic_streambuf::sgetn should return streamsize, not int_type
 
27.5.2:
basic_streambuf::sungetc should return int_type, not int
 
27.5.2:
basic_streambuf::sputc should return int_type, not int
 
27.5.2:
basic_streambuf::sputn should return streamsize, not int_type
 
27.5.2.2.3:
In in_avail Returns: gend() should be egptr() and gnext() should be
gptr().
 
27.5.2.2.3:
basic_streambuf::sbumpc Returns should not say the function
converts *gptr() to char_type. The function returns the int_type
result of the call.
 
27.5.2.2.3:
basic_streambuf::sgetc Returns should not say the function
converts *gptr() to char_type. The function returns the int_type
result of the call.
 
27.5.2.2.3:
basic_streambuf::sgetn should return streamsize, not int.
 
27.5.2.2.4:
basic_streambuf::sungetc should return int_type, not int.
 
27.5.2.2.4:
basic_streambuf::sputc should return int_type, not int.
 
27.5.2.2.5:
basic_streambuf::sputc does not return *pptr(), which points at
storage with undefined content. It returns traits::to_int_type(c).
 
27.5.2.4.2:
basic_streambuf::sync now requires that buffered input characters
``are restored to the input sequence.'' This is a change made without
approval. It is also difficult, or even impossible, to do so for
input streams on some systems, particularly for interactive or
pipelined input. The Standard C equivalent of sync leaves
input alone. Posix *discards* interactive input. This added requirement
is none of the above. It should be struck.
 
27.5.2.4.3:
basic_streambuf::showmanyc Returns has been corrupted. The function
should return the number of characters that can be read with no fear
of an indefinite wait while underflow obtains more characters from the
input sequence. traits::eof() is only part of the story. Needs to be
restored to the approved intent. (See footnote 218.)
 
27.5.2.4.3:
basic_streambuf::showmanyc Notes says the function uses traits::eof().
Not necessarily true.
 
27.5.2.4.3:
Footnote 217 is nonsense unless showmany is corrected to showmanyc.
 
27.5.2.4.3:
basic_streambuf::underflow has two Returns clauses. Should combine
them to be comprehensive.
 
27.5.2.4.3:
basic_streambuf::uflow default behavior ``does'' gbump(1),
not gbump(-1). It also returns the value of *gptr() *before*
``doing'' gbump.
 
27.5.2.4.3:
basic_streambuf::uflow has a nonsense Returns clause. Should be struck.
 
27.5.2.4.4:
basic_streambuf::pbackfail argument should be int_type, not int.
 
27.5.2.4.4:
basic_streambuf::pbackfail Notes begins a sentence with ``Other
calls shall.'' Can't apply ``shall'' to user program behavior,
by the accepted conformance model.
 
27.6:
<iomanip> synopsis has includes for <istream> and <ostream>, but
none of the declarations appear to depend on either of these headers.
They should be replaced by an include for <ios>.
 
27.6:
<iomanip> does *not* define a single type smanip. Rather, it
defines at least two different types which depend on the type
of the function argument. Should probably say that each function
returns some unspecified type suitable for inserting into an
arbitrary basic_ostream object or extracting from a basic_istream
object.
 
27.6.1.1:
basic_istream::seekg(pos_type&) and basic_istream::seekg(off_type&,
ios_base::seekdir) should both have const first parameters.
 
27.6.1.1:
basic_istream paragraph 2 says extractors may call rdbuf()->sbumpc(),
rdbuf()->sgetc(), or ``other public members of istream except that
they do not invoke any virtual members of rdbuf() except uflow().''
This is a constraint that was never approved. Besides, rdbuf()->sgetc()
invokes underflow(), as does uflow() itself, and the example
of ipfx in 27.6.1.1.2 uses rdbuf()->sputbackc(). The added constraint
should be struck.
 
27.6.1.1:
basic_istream definition, paragraph 4 is confusing, particularly in
the light of similar errors in 27.6.2.1 and 27.6.2.4.2 (basic_ostream).
It says, ``If one of these called functions throws an exception, then
unless explicitly noted otherwise the input function calls
setstate(badbit) and if badbit is on in exception() rethrows the
exception without completing its actions.'' But the setstate(badbit)
call may well throw an exception itself, as is repeatedly pointed
out throughout the draft. In that case, it will not return control
to the exception handler in the input function. So it is foolish to
test whether badbit is set -- it can't possibly be. Besides, I can
find no committee resolution that calls for exceptions() to be
queried in this event.
An alternate reading of this vague sentence implies that setstate
should rethrow the exception, rather than throw ios_base::failure,
as is its custom. But the interface to setstate provides no way
to indicate that such a rethrow should occur, so these putative
semantics cannot be implemented.
The fix is to alter the ending of the sentence to read, ``and if
setstate returns, the function rethrows the exception without
completing its actions.'' (It is another matter to clarify what
is meant by ``completing its actions.'')
 
27.6.1.1.2:
basic_istream::ipfx Notes says the second argument to traits::
is_whitespace is ``const locale *''. The example that immediately
follows makes clear that it should be ``const ctype<charT>&''.
 
27.6.1.1.2:
Footnote 222 makes an apparently normative statement in
a non-normative context.
 
27.6.1.2.1:
basic_istream description is silent on how void* is converted.
Can an implementation use num_get<charT>::get for one of the
integer types? Must it *not* use this facet? Is a version of
get missing in the facet? Needs to be clarified.
 
7766.1.2.1:
Example of call to num_get<charT>::get has nonsense for first two
arguments. Instead of ``(*this, 0, '' they should be
be ``(istreambuf_iterator<charT>(rdbuf()),
istreambuf_iterator<charT>(0), ''
 
27.6.1.2.1:
Example of numeric input conversion says ``the conversion occurs
`as if' it performed the following code fragment.'' But that
fragment contains the test ``(TYPE)tmp != tmp'' which often has
undefined behavior for any value of tmp that might yield a true
result. The test should be replaced by a metastatement such as
``<tmp can be safely converted to TYPE>''. (Then num_get needs
a version of get for extracting type float to make it possible
to write num_get in portable C++ code.)
 
27.6.1.2.1:
Paragraph 4, last sentence doesn't make sense. Perhaps ``since the
flexibility it has been...'' should be, ``since for flexibility
it has been...'' But I'm not certain. Subsequent sentences are
even more mysterious.
 
27.6.1.2.1:
Use of num_get facets to extract numeric input leaves very unclear
how streambuf exceptions are caught and properly reported. 22.2.2.1.2
makes clear that the num_get::get virtuals call setstate, and hence
can throw exceptions *that should not be caught* within any of the
input functions. (Doing so typically causes the input function to
call setstate(badbit), which is *not* called for as part of reporting
eof or scan failure. On the other hand, the num_get::get virtuals
are called with istreambuf_iterator arguments, whose very constructors
might throw exceptions that need to be caught. And the description of
the num_get::get virtuals is silent on the handling of streambuf
exceptions.
So it seems imperative that the input functions wrap each call to
a num_get::get function in a try block, but doing so will intercept
any exceptions thrown by setstate calls within the num_get::get
functions.
A related problem occurs when eofbit is on in exceptions and the
program attempts to extract a short at the very end of the file.
If num_get::get(..., long) calls setstate, the failure exception
will be thrown before the long value is converted and stored in
the short object, which is *not* the approved behavior.
The best fix I can think of is to have the num_get::get
functions return an ios_base::iostate mask which specifies what
errors the caller should report to setstate. The ios& argument
could be a copy of the actual ios for the stream, but with
exceptions cleared. The num_get::get functions can then continue
to call setstate directly with no fear of throwing an exception.
But all this is getting very messy for such a time critical
operation as numeric input.
 
27.6.1.2.2:
basic_istream::operator>>(char_type *) extracts an upper limit of
numeric_limits<int>::max() ``characters.'' This is a silly and
arbitrary number, just like its predecessor INT_MAX for
characters of type char. A more sensible value is size_t(-1) /
sizeof (char_type) - 1. Could just say ``the size of the largest
array of char_type that can also store the terminating null.''
basic_istream::operator>>(bool&) has nonsense for its first
two arguments. Should be
  istreambuf_iterator<charT, traits>(rdbuf()),
  istreambuf_iterator<charT, traits>(0), etc.
 
27.6.1.2.2:
basic_istream::(bool&  paragraph 3 describes the behavior of
num_get::get. Description belongs in clause 22.
 
27.6.1.2.2:
basic_istream::operator>>(unsigned short&) cannot properly check
negated inputs. The C Standard is clear that -1 is a valid field,
yielding 0xffff (for 16-bit shorts). It is equally clear that
0xffffffff is invalid. But num_get::get(... unsigned long&)
delivers the same bit pattern for both fields (for 32-bit
longs), with no way to check the origin. One fix is to have
the extractor for unsigned short (and possibly for unsigned int)
pick off any '-' flag and do the checking and negating properly,
but that precludes a user-supplied replacement for the num_get
facet from doing some other magic. Either the checking rules
must be weakened over those for Standard C, the interface to
num_get must be broadened, or the extractor must be permitted
to do its own negation.
 
27.6.1.2.2:
basic_istream::operator>>(basic_streambuf *sb) now says, ``If sb is
null, calls setstate(badbit).'' This requirement was added without
committee approval. It is also inconsistent with the widespread
convention that badbit should report loss of integrity of the stream
proper (not some other stream). A null sb should set failbit.
 
27.6.1.2.2:
basic_istream::operator>>(basic_streambuf<charT,traits>* sb), last
line of Effects paragraph 4 can't happen. Previous sentence says,
``If the function inserts no characters, it calls setstate(failbit),
which may throw ios_base failure. Then the last sentence says,
``If failure was due to catching an exception thrown while extracting
characters from sb and failbit is on in exceptions(), then the caught
exception is rethrown.'' But in this case, setstate has already thrown
ios_base::failure. Besides, I can find no committee resolution
that calls for exceptions() to be queried in this event.
In fact, the approved behavior was simply to terminate the copy
operation if an extractor throws an exception, just as for
get(basic_streambuf&) in 27.6.1.3. Last sentence should be struck.
 
27.6.1.3:
basic_istream::get(basic_streambuf& sb) Effects says it inserts
characters ``in the output sequence controlled by rdbuf().''
Should be the sequence controlled by sb.
 
27.6.1.3:
basic_istream::readsome refers several times to in_avail(), which
is not defined in the class. All references should be to
rdbuf()->in_avail(). And the description should specify what
happens when rdbuf() is a null pointer. (Presumably sets badbit.)
 
27.6.1.3:
basic_istream::readsome is now defined for rdbuf()->in_avail() < 0.
The original proposal defined only the special value -1. Otherwise,
it requires that rdbuf()->in_avail >= 0. Should be restored.
 
27.6.1.3:
basic_istream::readsome cannot return read, as stated. That
function has the wrong return type. Should return gcount().
 
27.6.1.3:
basic_istream::putback does *not* call ``rdbuf->sputbackc(c)''.
It calls ``rdbuf()->sputbackc(c)'' and then only if rdbuf()
is not null.
 
27.6.1.3:
basic_istream::unget does *not* call ``rdbuf->sungetc(c)''.
It calls ``rdbuf()->sungetc(c)'' and then only if rdbuf()
is not null.
 
27.6.1.3:
basic_istream::sync describes what happens when rdbuf()->pubsync()
returns traits::eof(), but that can't happen in general because
pubsync returns an int, not an int_type. This is an unauthorized,
and ill-advised, change from the original EOF. Return value should
also be EOF.
 
27.6.1.3:
basic_istream::sync Notes says the function uses traits::eof().
Obviously it doesn't, as described above. Clause should be struck.
 
27.6.2.1:
basic_ostream::seekp(pos_type&) and basic_ostream::seekp(off_type&,
ios_base::seekdir) should both have const first parameters.
 
27.6.2.1:
basic_ostream definition, last line of paragraph 2 can't happen.
It says, ``If the called
function throws an exception, the output function calls
setstate(badbit), which may throw ios_base::failure, and if badbit
is on in exceptions() rethrows the exception.'' But in this case,
setstate has already thrown ios_base::failure. Besides, I can find
no committee resolution that calls for exceptions() to be queried
in this event. Last sentence should end with, ``and if setstate
returns, the function rethrows the exception.''
 
27.6.1.2.1:
Use of num_put facets to insert numeric output leaves very unclear
how output failure is reported. Only the ostreambuf_iterator knows
when such a failure occurs. If it throws an exception, the calling
code in basic_ostreambuf is obliged to call setstate(badbit) and
rethrow the exception, which is *not* the approved behavior
for failure of a streambuf primitive.
Possible fixes are: have ostreambuf_iterator report a specific
type of exception, have ostreambuf_iterator remember a failure
for later testing, or give up on restoring past behavior. Something
*must* be done in this area, however.
 
e7.6.2.4.1:
Tabie 76 is mistitled. It is not just about floating-point conversions.
 
27.6.2.4.1:
Table 77 has an unauthorized change of rules for determining fill
padding. It gives the three defined states of flags() & adjustfield as
left, internal, and otherwise. It should be right, internal, and
otherwise. Needs to be restored to the earlier (approved) logic.
 
27.6.2.4.2:
basic_ostream<<operator<<(bool) should use ostreambuf_iterator,
not istreambuf_iterator. The first argument is also wrong in the
call to num_put::put.
 
27.6.2.4.2:
basic_ostream::operator<<(basic_streambuf *sb) says nothing about
sb being null, unlike the corresponding extractor (27.6.1.2.2).
Should either leave both undefined or say both set failbit.
 
27.6.2.4:
basic_ostream::operator<<(streambuf *) says nothing about the failure
indication when ``inserting in the output sequence fails''. Should
say the function sets badbit.
 
27.6.2.4.2:
basic_ostream::operator<<(basic_streambuf<charT,traits>* sb), last
line of Effects paragraph 2 can't happen. Previous sentence says that
if ``an exception was thrown while extracting a character, it calls
setstate(failbit) (which may throw ios_base::failure).'' Then the
last sentence says, ``If an exception was thrown while extracting a
character and failbit is on in exceptions() the caught exception
is rethrown.'' But in this case, setstate has already thrown
ios_base::failure. Besides, I can find no committee resolution
that calls for exceptions() to be queried in this event. And an
earlier sentence says unconditionally that the exception is rethrown.
Last sentence should be struck.
 
27.6.2.5:
basic_ostream::flush can't test for a return of traits::eof() from
basic_streambuf::pubsync. It tests for EOF.
 
27.6.3:
``headir'' should be ``header.''
 
27.6.3:
<iomanip> does *not* define a single type smanip. Rather, it
defines at least two different types which depend on the type
of the function argument. Should probably say that each function
returns some unspecified type suitable for inserting into an
arbitrary basic_ostream object or extracting from a basic_istream
object.
 
27.7:
<sstream> synopsis refers to the nonsense class int_charT_traits.
It should be ios_traits.
 
27.7:
Table 77 (<cstdlib> synopsis) is out of place in the middle of
the presentation of <sstream>.
 
27.7.1:
basic_stringbuf::basic_stringbuf(basic_string, openmode) Effects
repeats the phrase ``initializing the base class with
basic_streambuf().'' Strike the repetition.
 
27.7.1:
basic_stringbuf::basic_stringbuf(basic_string, openmode) Postconditions
requires that str() == str. This is true only if which has in set.
Condition should be restated.
 
27.7.1:
Table 78 describes calls to setg and setp with string
arguments, for which no signature exists. Needs to be recast.
 
27.7.1:
basic_stringbuf::str(basic_string s) Postconditions
requires that str() == s. This is true only if which had in set
at construction time. Condition should be restated.
 
27.7.1.2:
Table 80 describes calls to setg and setp with string
arguments, for which no signature exists. Needs to be recast.
 
27.7.1.3:
basic_stringbuf::underflow Returns should return int_type(*gptr()),
not char_type(*gptr()).
 
27.7.1.3:
basic_stringbuf::pbackfail returns c (which is int_type) in first case,
char_type(c) in second case. Both cases should be c.
 
27.7.1.3:
basic_stringbuf::pbackfail supposedly returns c when c == eof().
Should return traits::not_eof(c).
 
27.7.1.3:
basic_stringbuf::seekpos paragraph 4 has ``positionedif'' run together.
 
27.8.1.1:
basic_filebuf paragraph 3 talks about a file being ``open for reading
or for update,'' and later ``open for writing or for update.''
But ``open for update'' is not a defined term. Should be struck
in both cases.
 
27.8.1.3:
basic_filebuf::is_open allegedly tests whether ``the associated file
is available and open.'' No definition exists for ``available.''
The term should be struck.
 
27.8.1.3:
basic_filebuf::open Effects says the function fails if is_open()
is initially false. Should be if initially true.
 
27.8.1.3:
basic_filebuf::open Effects says the function calls the default
constructor for basic_streambuf. This is nonsense. Should say,
at most, that it initializes the basic_filebuf as needed, and
then only after it succeeds in opening the file.
 
27.8.1.3:
Table 83 has a duplicate entry for file open mode ``in | out''.
 
27.8.1.4:
filebuf::showmanyc (and several overriden virtual functions that
follow) have a Requires clause that says ``is_open == true.''
The behavior of all these functions should be well defined
in that event, however. Typically, the functions all fail.
The Requires clause should be struck in all cases.
 
27.8.1.4:
filebuf::showmanyc Effects says the function ``behaves the same
as basic_streambuf::showmanyc.'' The description adds nothing
and should be struck.
 
27.8.1.4:
basic_filebuf::underflow effects shows arguments to convert as
``st,from_buf,from_buf+FSIZE,from_end,to_buf, to_buf+to_size, to_end''.
st should be declared as an object of type state_type, and n should
be defined as the number of characters read into from_buf. Then the
arguments should be ``st, from_buf, from_buf + n, from_end, to_buf,
to_buf + TSIZE, to_end''. Also, template parameter should be
``traits::state_type,'' not ``ios_traits::state_type.''
 
27.8.1.4:
basic_filebuf::underflow is defined unequivocally as the function
that calls codecvt, but there are performance advantages to having
this conversion actually performed in uflow. If the specification
cannot be broadened sufficiently to allow either function to do
the translation, then uflow loses its last rationale for being
added in the first place. Either the extra latitude should be
granted implementors or uflow should be removed from basic_streambuf
and all its derivatives.
 
27.8.1.4:
basic_filebuf::pbackfail(traits::eof()) used to return a value
other than eof() if the function succeeded in backing up the
input. Now the relevant Returns clause says the function returns
the metacharacter c, which is indistinguishable from a failure
return. This is an unapproved change. Should probably say the
function returns traits::not_eof(c).
 
27.8.1.4:
basic_filebuf::pbackfail Notes now says ``if is_open() is false,
the function always fails.'' This is an unapproved change.
The older wording should be restored.
 
27.8.1.4:
basic_filebuf::pbackfail Notes now says ``the function does not
put back a character directly to the input sequence.'' This is
an unapproved change and not in keeping with widespread practice.
The older wording should be restored.
 
27.8.1.4:
basic_filebuf::pbackfail has a Default behavior clause.
Should be struck.
 
27.8.1.4:
basic_filebuf::overflow effects shows arguments to convert as
``st,b(),p(),end,buf,buf+BSIZE,ebuf''. st should be declared as
an object of type state_type. Then the arguments should be
``st, b, p, end, buf, buf + BSIZE, ebuf''. Also, template parameter
should be ``traits::state_type,'' not ``ios_traits::state_type.''
 
27.8.1.4:
basic_filebuf::overflow doesn't say what it returns on success.
Should say it returns c.
 
27.8.1.4:
basic_filebuf::setbuf has no semantics. Needs to be supplied.
 
27.8.1.4:
basic_filebuf::seekoff Effects is an interesting exercise in creative
writing. It should simply state that if the stream is opened as a
text file or has state-dependent conversions, the only permissible
seeks are with zero offset relative to the beginning or current
position of the file. (How to determine that predicate is another
matter -- should state for codecvt that even a request to convert
zero characters will return noconv.) Otherwise, behavior is largely
the same as for basic_stringstream, from whence the words should be
cribbed. The problem of saving the stream state in a traits::pos_type
object remains unsolved. The primitives described for ios_traits
are inadequate.
 
27.8.1.4:
basic_filebuf::seekpos has no semantics. Needs to be supplied.
 
27.8.1.4:
basic_filebuf::sync has no semantics. Needs to be supplied.
 
27.8.1.4:
basic_filebuf::imbue has silly semantics. Whether or not sync()
succeeds has little bearing on whether you can safely change
the working codecvt facet. The most sensible thing is to establish
this facet at construction. (Then pubimbue and imbue can be
scrubbed completely.) Next best is while is_open() is false.
(Then imbue can be scrubbed, since it has nothing to do.)
Next best is to permit any imbue that doesn't change the facet
or is at beginning of file. Next best is to permit change of facet
any time provided either the current or new facet does not mandate
state-dependent conversions. (See comments under seekoff.)
 
27.8.1.7:
basic_filebuf::rdbuf should not have explicit qualifier.
 
27.8.1.9:
basic_ofstream::basic_ofstream(const char *s, openmode mode = out)
has wrong default second argument. It should be `out | trunc', the
same as for basic_ofstream::open (in the definition at least).
27.8.1.10:
basic_ofstream::open(const char *s, openmode mode = out)
has wrong default second argument. It should be `out | trunc', the
same as for basic_ofstream::open in the definition.
 
27.8.2:
<cstdio> synopsis has two copies of tmpfile and vprintf,
no vfprintf or putchar.
 
27.8.2:
<cwchar> summary should also list the type wchar_t. Aside from the
addition of the (incomplete) type struct tm, this table 84 is
identical to table 44 in 21.2. It is not clear what purpose either
table serves; it is less clear what purpose is served by repeating
the table.
 
27.8.2:
See Also reference for <wchar> should be 7.13.2, not 4.6.2.
 
 
-------- Annex D Issues -------
 
D.2:
Functions overloaded on io_state, open_mode, and seek_dir ``call
the corresponding member function.'' But no hint is given as to
what constitutes ``correspondence.''
 
D.3.1:
Base class for class strstreambuf should be basic_streambuf<char>,
or streambuf, not streambuf<char>.
 
D.3.1:
strstreambuf::freeze default bool argument should be true, not 1.
 
D.3.1:
strstreambuf::pcount should return streamsize, not int
D.3.11:
strstreambuf::strstreambuf(char *, streamsize, char *) paragraph 3
has wrong argument for setp. It should be:
setp(pbeg_arg, gbeg_arg + N). (This is an ancient typo -- clearly
wrong because it violates the stated constraints on the size of
the working array.)
 
D.3.1.2:
strstreambuf::freeze default value should be true, not 1.
 
D.3.1.3:
strstreambuf::overflow, etc. still have references to int_type,
ios_traits<char>, etc. Should be reconciled with synopsis.
 
D.3.1.3:
strstreambuf::overflow has numerous references to ``eof()'', which
no longer exists. All should be changed to EOF.
 
D.3.1.3:
strstreambuf::overflow says it returns ``(char)c'' sometimes,
but this can pun with EOF if char has a signed representation.
More accurate to say it returns (unsigned char)c.
 
D.3.1.3:
strstreambuf::pbackfail says it returns ``(char)c'' sometimes,
but this can pun with EOF if char has a signed representation.
More accurate to say it returns (unsigned char)c.
 
D.3.1.3:
strstreambuf::pbackfail says it returns ``(char)c'' when c == EOF,
but this can pun with EOF if char has a signed representation.
More accurate to say it returns something other than EOF.
 
D.3.1.3:
Default arguments to strstreambuf::seekoff third argument must be
qualified with ios::.
 
D.3.1.3:
strstreambuf::seekoff should position both streams even for
way == ios::cur. It then uses the get pointer as a starting point.
 
D.3.1.3:
The ``otherwise'' at the beginning of paragraph 8 is a nonsequitir.
 
D.3.1.3:
strstreambuf::setbuf has a Default behavior clause, which is not
appropriate for a derived stream buffer. It also adds nothing to
the definition in the base class. The entire description should
be struck.
 
D.3.2:
Base class for class istrstream should be basic_istream<char>,
not istream<char>.
 
D.3.3:
Base class for class ostrstream should be basic_ostream<char>,
not ostream<char>.
 
D.3.3:
ostrstream::ostrstream(char *, int, openmode) should have second
argument type of streamsize.
 
D.3.3:
ostrstream::freeze should have argument ``bool freezefl = true''
instead of ``int freezefl = true''.