Listing C
// message_handler_log.h
 
#ifndef MESSAGE_HANDLER_LOG_H
#define MESSAGE_HANDLER_LOG_H
 
#include <ostream>
#include <sstream>
#include <memory>
#include <assert.h>
 
// forward declaration(s)
template< class char_type, class traits_type = std::char_traits< char_type> >
    class basic_message_handler_log;
 
//    represents the stream buffer for a message_handler_log (see below)
//    Note: NOT thread-safe
template< class char_type , class traits_type = std::char_traits< char_type> >
    class basic_message_handler_log_streambuf
        : public std::basic_streambuf< char_type, traits_type>
{
private:
    friend class basic_message_handler_log< char_type, traits_type>;
    typedef std::basic_streambuf< char_type, traits_type> streambuf_type;
    typedef basic_message_handler_log< char_type, traits_type> ostream_type;
    // base class
    typedef std::basic_streambuf< char_type, traits_type> base_class;
 
#ifndef __GNUC__
    using typename base_class::int_type;
    using typename base_class::pos_type;
    using typename base_class::off_type;
#endif
 
    enum
    { _BADOFF = -1 /* bad offset - for positioning functions */ };
protected:
    // input, not allowed
    virtual int_type pbackfail(int_type = traits_type::eof())
    {
        // only for output, not for input
        assert( false);
        return (traits_type::eof());
    }
    virtual int showmanyc()
    {
        // only for output, not for input
        assert( false);
        return 0;
    }
    virtual int_type underflow()
    {
        // only for output, not for input
        assert( false);
        return (traits_type::eof());
    }
    virtual int_type uflow()
    {
        // only for output, not for input
        assert( false);
        return (traits_type::eof());
    }
   
    virtual std::streamsize xsgetn(char_type *, std::streamsize)
    {
        // only for output, not for input
        assert( false);
        return 0;
    }
   
    // positioning, not allowed - we're a log
    virtual pos_type seekoff(off_type, std::ios_base::seekdir,
        std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
    {
        // we don't allow positioning
        assert( false);
        return (std::streampos( _BADOFF));
    }
    virtual pos_type seekpos(pos_type,
        std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
    {
        // we don't allow positioning
        assert( false);
        return (std::streampos( _BADOFF));
    }
   
    // output functions
 
    // called to write out from the internal
    // buffer, into the external buffer
    virtual int sync()
    {
       m_pOwnerStream->on_new_message( get_stream_buffer().str() );
        m_pStreamBuffer = std::auto_ptr< string_stream_type>( new string_stream_type);
        return 0;
    }
    virtual streambuf_type *setbuf( char_type * buffer, std::streamsize n)
    {
        // ... note: this function MUST be called
        //    before working with this stream buffer
        // we don't use a buffer - we forward everything
        assert( buffer == NULL && n == 0);
        this->setp( NULL, NULL);
        return this;
    }
    // write the characters from the buffer
    // to their real destination
    virtual int_type overflow(int_type nChar = traits_type::eof())
    {
        if ( traits_type::not_eof( nChar))
            get_stream_buffer() << ( char_type)nChar;
        return traits_type::not_eof( nChar);
    }   
    virtual std::streamsize xsputn(const char_type *S, std::streamsize N)
    {
        get_stream_buffer().write( S, N);
        return N;
    }
 
public:
    basic_message_handler_log_streambuf()
        : m_pStreamBuffer( new string_stream_type) {}
private:
    typedef std::basic_ostringstream< char_type> string_stream_type;
    string_stream_type & get_stream_buffer()
    { return *m_pStreamBuffer; }
private:
    // holds the Message, until it's flushed
    std::auto_ptr< string_stream_type> m_pStreamBuffer;
    // the Message Handler Log - where we write into
    ostream_type * m_pOwnerStream;
};
 
// derive your class from this and implement the PROTECTED on_new_message function
template< class char_type, class traits_type >
    class basic_message_handler_log
        : public std::basic_ostream< char_type, traits_type>
{
    typedef basic_message_handler_log_streambuf< char_type, traits_type> handler_streambuf_type;
    friend class basic_message_handler_log_streambuf< char_type, traits_type>;
    typedef std::basic_ostream< char_type, traits_type> base_class;
    typedef std::basic_ostringstream< char_type> string_stream_type;
 
protected:
    typedef std::basic_string< char_type> string_type;
 
    basic_message_handler_log()
       : m_StreamBuf(),
          base_class( NULL)
    {
        m_StreamBuf.m_pOwnerStream = this;
        this->init( &m_StreamBuf);
        m_StreamBuf.pubsetbuf( NULL, 0);
    }
 
    basic_message_handler_log( const basic_message_handler_log< char_type, traits_type> & from)
        : m_StreamBuf(),
          base_class( NULL)
    {
        m_StreamBuf.m_pOwnerStream = this;
        this->init( &m_StreamBuf);
        m_StreamBuf.pubsetbuf( NULL, 0);
    }
 
    virtual ~basic_message_handler_log() {}
protected:
    virtual void on_new_message( const string_type & new_message_log) = 0;
public:
    // our stream buffer
    handler_streambuf_type m_StreamBuf;
};
 
typedef basic_message_handler_log< char> message_handler_log;
typedef basic_message_handler_log< wchar_t> wmessage_handler_log;
 
#endif