You don't want to modify std::cout.
Instead, you want to create a specialised std::streambuf that writes to two buffers rather than one. For example;
#include <streambuf> template <typename char_type, typename traits = std::char_traits<char_type> > class basic_teebuf: public std::basic_streambuf<char_type, traits> { public: typedef typename traits::int_type int_type; basic_teebuf(std::basic_streambuf<char_type, traits> * sb1, std::basic_streambuf<char_type, traits> * sb2) : sb1(sb1) , sb2(sb2) { } protected: // override virtuals inherited from std::basic_streambuf virtual int sync() { int const r1 = sb1->pubsync(); int const r2 = sb2->pubsync(); return r1 == 0 && r2 == 0 ? 0 : -1; } virtual int_type overflow(int_type c) { int_type const eof = traits::eof(); if (traits::eq_int_type(c, eof)) { return traits::not_eof(c); } else { char_type const ch = traits::to_char_type(c); int_type const r1 = sb1->sputc(ch); int_type const r2 = sb2->sputc(ch); return traits::eq_int_type(r1, eof) || traits::eq_int_type(r2, eof) ? eof : c; } } private: std::basic_streambuf<char_type, traits> * sb1; std::basic_streambuf<char_type, traits> * sb2; }; typedef basic_teebuf<char> teebuf;
Then you need to create a specialised ostream which uses such a buffer
#include <ostream> class teestream : public std::ostream { public: // Construct an ostream which tees output to the supplied // ostreams. teestream(std::ostream & o1, std::ostream & o2); private: teebuf tbuf; }; teestream::teestream(std::ostream & o1, std::ostream & o2) : std::ostream(&tbuf) , tbuf(o1.rdbuf(), o2.rdbuf()) { }
All the above does is create a specialised std::ostream that uses our specialised buffer, which in turn makes use of two buffers.
Now, our teestream needs to be initialised using two streams. For example
#include <fstream> #include <iostream> // include the preceding definition of teestream here int main() { std::ofstream logfile("hello-world.log"); teestream tee(std::cout, logfile); // tee is now a stream that writes the same output to std::cout and logfile tee << "Hello, world!\n"; return 0; }
The advantage of this is that all stream insertions (operator <<) will work with our teestream - even for classes with overloaded versions.
When main() returns, the streams will also be closed cleanly.
I've written the specalised streambuf as a template (std::streambuf is a specialisation of a templated class named std::basic_streambuf). For generality, it would probably be better to do the same with the stream (using the fact that std::ostream is also a specialisation of a templated std::basic_ostream). I leave that sort of generalisation as an exercise.
.log()method, that, depending on implementation can log to file, write to stdout etc, rather than trying to overload free functions fromstdnamespace. It will be far more OO and look less crap.std::clogand redirecting its output to a file:std::cout.rdbuf(logfile.rdbuf());?