My current implementation, simplified:
#include <string>
#include <memory>
class Log
{
public:
~Log() {
// closing file-descriptors, etc...
}
static void LogMsg( const std::string& msg )
{
static std::unique_ptr<Log> g_singleton;
if ( !g_singleton.get() )
g_singleton.reset( new Log );
g_singleton->logMsg( msg );
}
private:
Log() { }
void logMsg( const std::string& msg ) {
// do work
}
};
In general, I am satisfied with this implementation because:
- lazy instantiation means I don’t pay unless I use it
- use of unique_ptr means automatic cleanup so valgrind is happy
- relatively simple, easy-to-understand implementation
However, the negatives are:
- singletons aren’t conducive to unit-testing
- dissonance in the back of my mind for introducing a pseudo-global (a bit of a code smell)
So here are my questions directed towards those developers who are successful in exorcising all singletons from their C++ code:
- What kind of non-Singleton implementation do you use for application-wide logging?
- Is the interface as simple and accessible as a Log::LogMsg() call above?
I want to avoid passing a Log instance all over my code, if at all possible – note: I am asking because, I, too, want to exorcise all Singletons from my code if there is a good, reasonable alternative.
First: the use of
std::unique_ptris unnecessary:Produces exactly the same lazy initialization and cleanup semantics without introducing all the syntax noise (and redundant test).
Now that is out of the way…
Your class is extremely simple. You might want to build a slightly more complicated version, typical requirements for log messages are:
on top of the message itself.
As such, it is perfectly conceivable to have several objects with different parameters:
And you usually wrap the access inside a macro for convenience:
Now, we can create a simple verbose logger:
And use it conveniently:
The purpose of this rant ? Not all that is a global need be unique. The uniqueness of Singletons is generally useless.
Note: if the bit of magic involving
std::ostringstreamscares you, this is normal, see this question