Many of the formatted output operator<< ( operator<< ) are written directly to the stream buffer. What you need to do to accomplish this in a general way is to get a class from std :: basic_streambuf, which forwards all the data to another std :: basic_streambuf, and then additionally creates a minimal implementation of std :: basic_ostream to make it easier to use your stream buffer.
I would not say that it is especially simple, but this is the only way to do it in a way that can affect all types of streams.
Here is an example of a minimal stream buffer that sends to another stream buffer (and performs some meaningless conversions to demonstrate what you can do) and an accompanying stream:
#include <iostream> #include <streambuf> template<typename CharType, typename Traits = std::char_traits<CharType> > class ForwardingStreamBuf : public std::basic_streambuf<CharType, Traits> { public: typedef Traits traits_type; typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; ForwardingStreamBuf(std::basic_streambuf<CharType, Traits> *baseStreamBuf) : _baseStreamBuf(baseStreamBuf) { } protected: virtual int_type overflow(int_type c = traits_type::eof()) { if( _baseStreamBuf == NULL ) return traits_type::eof(); if( traits_type::eq_int_type(c, traits_type::eof()) ) return traits_type::not_eof(c); else { CharType ch = traits_type::to_char_type(c); if( ch >= 'A' && ch <= 'z' ) ch++; // Do some meaningless transformation return _baseStreamBuf->sputc(ch); } } virtual int sync() { if( _baseStreamBuf == NULL ) return -1; else return _baseStreamBuf->pubsync(); } private: std::basic_streambuf<CharType, Traits> *_baseStreamBuf; }; template<typename CharType, typename Traits = std::char_traits<CharType> > class ForwardingStream : public std::basic_ostream<CharType, Traits> { public: ForwardingStream(std::basic_ostream<CharType, Traits> &stream) : std::basic_ostream<CharType, Traits>(NULL), _buffer(stream.rdbuf()) { this->init(&_buffer); } ForwardingStreamBuf<CharType, Traits>* rdbuf() const { return &_buffer; } private: ForwardingStreamBuf<CharType, Traits> _buffer; };
This can be used very simply:
int main() { ForwardingStream<char> test(std::cout); test << "Foo" << std::endl; }
Gpp will be Gpp . Hope this helps you along the way.
source share