The way you modify the behavior of std::ostream
is not by overloading any of the output operators! Instead, you derive a class from std::streambuf
and override the virtual
functions overflow()
and sync()
. In you case you'd probably create a filtering stream buffer, i.e., you'd take another std::streambuf
as argument and write a somehow modified stream of characters to this stream buffer.
Here is a quick example:
#include <iostream>
class prefixbuf
: public std::streambuf
{
std::string prefix;
std::streambuf* sbuf;
bool need_prefix;
int sync() {
return this->sbuf->pubsync();
}
int overflow(int c) {
if (c != std::char_traits<char>::eof()) {
if (this->need_prefix
&& !this->prefix.empty()
&& this->prefix.size() != this->sbuf->sputn(&this->prefix[0], this->prefix.size())) {
return std::char_traits<char>::eof();
}
this->need_prefix = c == '
';
}
return this->sbuf->sputc(c);
}
public:
prefixbuf(std::string const& prefix, std::streambuf* sbuf)
: prefix(prefix)
, sbuf(sbuf)
, need_prefix(true) {
}
};
class oprefixstream
: private virtual prefixbuf
, public std::ostream
{
public:
oprefixstream(std::string const& prefix, std::ostream& out)
: prefixbuf(prefix, out.rdbuf())
, std::ios(static_cast<std::streambuf*>(this))
, std::ostream(static_cast<std::streambuf*>(this)) {
}
};
int main()
{
oprefixstream out("prefix: ", std::cout);
out << "hello
"
<< "world
";
}
Stream buffers conceptually keep an internal buffer which is, however, not set up in the example above. Every time there is no space for a character to be written to the output buffer, the virtual
function overflow()
is called with a character (it may also be called with the special value std::char_traits<char>::eof()
which is typically used to flush the buffer). Since there is no buffer, overflow()
will be called for every character. All this function does is to see if it needs to write a prefix and, if so, writes the prefix
. In case a newline '
'
is written, the function remembers that it needs to write the prefix
if another character is written. It then just forwards writing of the character to the underlying stream buffer.
The virtual
function sync()
is used to synchronize the stream with its external representation. For a stream buffer keeping a buffer it makes sure that any buffer is written. Since the prefixbuf
doesn't really keep a buffer, all it needs to is to delegate the sync()
request to the underlying stream buffer by calling pubsync()
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…