One solution is to duplicate everything that is written in cerr, for example, a file.
This is a helper class:
class CTee {
public:
CTee(ostream &s1, ostream &s2) : m_s1(s1), m_s1OrigBuf(s1.rdbuf()), m_teebuf(s1.rdbuf(), s2.rdbuf()) { s1.rdbuf(&m_teebuf); }
~CTee() { m_s1.rdbuf(m_s1OrigBuf); }
private:
CTee &operator =(CTee &rhs);
class CTeeBuf : public streambuf {
public:
CTeeBuf(streambuf* sb1, streambuf* sb2) : m_sb1(sb1), m_sb2(sb2) {}
protected:
virtual int_type overflow(int_type c) {
if(streambuf::traits_type::eq_int_type(c, streambuf::traits_type::eof()))
return c;
else {
m_sb1->sputc((streambuf::char_type)c);
return m_sb2->sputc((streambuf::char_type)c);
}
}
virtual int sync() {
m_sb1->pubsync();
return m_sb2->pubsync();
}
streambuf *m_sb1, *m_sb2;
};
ostream &m_s1;
streambuf * const m_s1OrigBuf;
CTeeBuf m_teebuf;
};
CTee takes ostreamfor duplication and ostreamfor duplication. It takes a duplicate, which should be duplicated, and replaces it rdbuf, streambufwhich is recorded using CTeeBuf (see CTEE ctor). CTeeBuf takes charwhich are written to it and forwards them in streambufboth ostream(see CTeeBuf :: overflow and CTeeBuf :: sync). CTEE dtor returns the changed streambufto its original value.
:
char logfilename[] = "myfile.log";
ofstream logfile(logfilename, ios_base::out | ios_base::app);
CTee tee(cerr, logfile);
, cerr, logfile ( tee). , cerr, logfile:
cerr << "error occured: ..." << endl;
, . ostream, - , CTeeBuf:: overflow , , .
. http://www.cs.technion.ac.il/~imaman/programs/teestream.html http://wordaligned.org/articles/cpp-streambufs.