User defined streambuf

Michel Decima michel.decima@cnet.francetelecom.fr
Sat Apr 1 00:00:00 GMT 2000


Hello everybody,

 Last week I downloaded the libstdc++-2.90.7 to play with
 standard library features like new streams, and I'm in 
 trouble now with my own streambufs.. Here is the code:

#include <cstdio>
#include <streambuf>
#include <iostream>

// A black hole streambuf, like /dev/null
// Defined 'by the book' from Nicolai M. Josuttis, 
// "The C++ Standard Library", p 668-670
// 
template<typename charT, typename traits = std::char_traits<charT> >
class basic_nullbuf : public std::basic_streambuf<charT, traits>
{
protected:
  virtual 
  int_type overflow(int_type c) {
      return traits::not_eof(c);
    }
};

typedef basic_nullbuf<char> nullbuf;
typedef basic_nullbuf<wchar_t> wnullbuf;

template<typename T>
void print(const T& x) {
  nullbuf ob;
  std::ostream out(&ob); 
  out << x << std::endl;

  if(!out) std::printf("error\n");
  else     std::printf("ok\n");
}

int main() 
{
  print( true );
  print( 3.14159 );
  print( 10 );
  print('x');
  print( "pipo");
}

With Sun CC 5.0, the program is doing fine (5 times ok), but with
gcc-2.95.2 and libstdc++-2.90.7, I got 3 ok and 2 error: for 
numeric values, my own overflow is called, and the stream state
is ok, but for caracters, overflow is not called (and the stream
become bad). So I added to the class basic_nullbuf the following
function :

  virtual 
  std::streamsize xsputn(const char*, std::streamsize n) {
    return n;
  }

and it worked (5 ok). But I think I don't have to provide this
hack to have a working streambuf (perhaps I'm wrong, I'm not
yet an ISO-C++-guru), because the default xsputn should call
overflow. 

The debugger told me that the default xsputn can't call the 
overflow because (see below) because the mode of my nullbuf
is the wrong one :

// g++-v3/include/bits/streambuf.tcc

template<typename _CharT, typename _Traits>
  streamsize
  basic_streambuf<_CharT, _Traits>::
  xsputn(const char_type* __s, streamsize __n) 
 {
   bool __testout = _M_mode & ios_base::out;  // here it is !
                                              // _M_mode = 0
   streamsize __retval = 0;

   if (__n && __testout) {    // __testout is false     
      ...
  }

Then I removed my own xsputn and added a constructor :

 basic_nullbuf() {
    _M_mode = std::ios::out;
  }

it worked (again 5 ok), but I don't think my code is
standard now...

So I think there is a problem here (or the book and CC are wrong).
Perhaps it is ok in a recent snapshot, and I should update.

--
mailto:michel.decima@cnet.francetelecom.fr 
Gates' Law: Every 18 months, the speed of software halves.


More information about the Libstdc++ mailing list