ISO/ IEC JTC1/SC22/WG21 N0791

** Title: Streambuf Iterator Cleanup
** Author: Nathan Myers <myersn@roguewave.com>
** Document: WG21/N0791 = X3J16/95-0191
** Sections: 24.4.3, 24.4.4, and 24.4.3.[234]
 
---------------------------------------------------------------
 
** Description
 
1. The typedefs declared in the streambuf iterators can lead to
   confusion because they have the same names as global typedefs.
   While this does not confuse compilers, it confuses readers,
   and is easily fixed.
2. The constructors cannot fail and do not need to throw exceptions,
   so they should be specified as such.  Also, there is no need for
   a default constructor for ostreambuf_iterator.
3. The overloaded global function iterator_category() must be specified
   as a template.
4. The description of semantics of istreambuf_iterator member operators
   is too vague: "Advances the iterator" and "Extract one character"
   are subject to interpretation.
5. The definition of operator== does not conform to the requirements
   for InputIterators.
 
In addition:
 
The ostreambuf_iterator that decouples iostream from the
locale facet interface provides no mechanism to allow output
errors to be detected.  ostream operators << need to be able
to detect output errors, even though the OutputIterator
idiom provides no mechanism for the facets to detect such
errors.
 
The caller of the facet member creates the ostreambuf_iterator
and is not constrained by the OutputIterator interface.  It
can query whether an error occurred.  We need only ensure that
errors are noted, that after an error subsequent output is absorbed
harmlessly, and that the error can be detected.
 
Finally, the interface for ostreambuf_error includes members
that are not part of the OutputIterator interface, and are
not useful to algorithms.
 
 
** Proposed Resolution
 
Amend the WP as follows:
 
In both 24.4.3 and 24.4.4, change the typedefs "streambuf", "istream",
and "ostream" to "streambuf_type", "istream_type", and "ostream_type",
respectively. In 24.4.3, replace the second and third constructors with:
 
  istreambuf_iterator(istream_type& s) throw();
  istreambuf_iterator(streambuf_type* s) throw();
 
In 24.4.4, replace the first three constructors with:
 
  ostreambuf_iterator(ostream_type& s) throw();
  ostreambuf_iterator(streambuf_type* s) throw();
 
(eliminating the default constructor) and in both 24.4.3 and 24.4.4,
change the declaration of the private member sbuf_ to:
 
  streambuf_type* sbuf_;  // exposition only
 
In 24.4.3.3:
 
-- Change operator*() description to: "Returns: sbuf_->sgetc()".
 
-- Change operator++() description to:
     "Effects: sbuf_->sbumpc(); Returns: *this."
   [or, if basic_streambuf<>::stossc() gets rehabilitated, then:
     "Effects: sbuf_->stossc(); Returns: *this." ]
 
-- Change operator++(int) description to:
     "Returns: proxy(sbuf_->sbumpc(),sbuf_)."
 
-- Change the definition of member equal():
     "Returns: true if both operands are at end-of-stream, or neither is
       end-of-stream, regardless of what stream they iterate over."
 
-- Change the definition of "istream_iterator<..>::proxy" to
   istreambuf_iterator<..>::proxy.
 
And also:
 
1. In Section 24.4.4.1 [lib.ostreambuf.iter.cons], for operator=(charT c),
   Add:
 
  Effects: If no previous call has returned traits::eof(),
    calls sbuf_->sputc(c).
 
2. Add a member:
 
   bool operator failed() const throw();
 
   Returns: Returns true if in any prior use of member operator=, the
     call to sbuf_->sputc() returned traits::eof(), or false otherwise.
 
3. In Section 24.4.4.2 [lib.ostreambuf.iter.ops], eliminate the
   ostreambuf_iterator member equal(ostreambuf_iterator& b).
 
4. In Section 24.4.4.3 [lib.ostreambuf.iterator.nonmembers],
   eliminate global operators == and !=.