I am trying to write a simple audit class that takes input via operator << and writes the audit after receiving a custom manipulator like this:
class C
I do something very similar for tracing, but use a stringstream. This ensures that all 3rd party operator << () and manipulators work. I also use the desctructor instead of the customer write manipulator.
class DebugStream
{
public:
DebugStream(short level, const char * file, int line) {
sstream << "L" << level << "\t" << file << "\t" << line << "\t";
}
~DebugStream() { write(sstream.str()); }
std::ostream & stream() { return sstream; }
private:
std::stringstream sstream;
DebugStream(const DebugStream &);
DebugStream & operator=(const DebugStream &);
};
This is then made available with some macros:
#define DBG_ERROR if (1<=dbg_level()) DebugStream(1, __FILE__, __LINE__).stream()
#define DBG_INFO if (2<=dbg_level()) DebugStream(2, __FILE__, __LINE__).stream()
And the code just uses the macros
DBG_INFO << "print some debug information";
You don't need a specific write manipulator to flush the data to the log file. When the anonymous DebugStream object goes out of scope (once control leaves the line) the the contents are automatically written.
Although I usually avoid macros in this case the use of the if statement means you don't have the overhead of building the trace line unless you actually require it.
Returning the ostream via the stream() method enables this to work for global member functions, as anonymous objects cannot be passed as non-const reference parameters.