Quick and simple debug stream for C++
by Ben
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
#include
#include
#include
// 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
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;