Ever need to set up a quick and simple debug/logging stream for your application without having to deal with large frameworks like log4cpp or *shudder* log4cxx? There’s also libcwd, which seems really neat, but also very large.
I didn’t want to use all that. I just needed a simple way to filter my output using streams without having if(…) blocks scattered all over the place. Here was my solution (I can’t remember if I came up with this on my own, or pawned it from someone else…if nothing else, I at least used the reference documentation for the boost Iostreams library). Read on to see what I did.
First, the header:
// debug.hpp #ifndef _DEBUG_H_ #define _DEBUG_H_ #include <iostream> #include <ostream> #include <streambuf> #include <boost/iostreams/concepts.hpp> // this defines a struct named options and // an instance of it called "opts" #include "main.hpp" struct nullstream : std::ostream { struct nullbuf : std::streambuf { int overflow(int c) { return traits_type::not_eof(c); } } _sbuf; nullstream() : std::ios(&_sbuf), std::ostream(&_sbuf) {} }; template<typename T> nullstream& operator<<(nullstream& ns, T) { return ns; } extern options opts; extern nullstream null; std::ostream& debug(short level); std::ostream& warn(); std::ostream& error(); #endif
Then the implementation:
// debug.cpp #include "debug.hpp" nullstream null; std::ostream& debug(short level) { if(opts.verbose < level) return null; return std::cout; } std::ostream& warn() { return std::cout << "[warn] "; } std::ostream& error() { return std::cerr << "[error] "; }
Very quick, very simple. Usage is just as easy. Instead of using std::cout like you often would, you just use debug(level), warn(), and error() in its place.
if(/*something important happens*/)
debug(0) << "whatever" << std::endl;
if(/*something interesting happens*/)
{
debug(1) << "something very interesting"
<< std::endl;
debug(2) << "something less interesting"
<< std::endl;
debug(7) << "the user should never know about this"
<< std::endl;
/* ... */
}
if(/* something bad but not fatal happens */)
{
warn() << "whoops, you messed up..."
<< "that's ok, continuing."
<< std::endl;
}
if(/* something fatal happens */)
error() << "serious fubar. quitting."
<< std::endl;