The singleton pattern names a programming structure used to replace global variables, without any of their downsizes. A plethora of implementation suggestions have been produced in the previous years. Most are needlessly complicated.
I am posting here a simple and effcient implementation of the singleon pattern. Using function templates and static variables, to get a reference to a singleton instance is no more than getting back a C++ reference. This implementation adds one line to each class that is to be enabled as a singleton, and no inheritance. That is quite useul, since inheritance usually means looking up virtual tables and following them.
First part: the instance
function.
instance
should return a reference to the given class. C++ Templates come to our help. C++ templates are like C prerocessor macros: they are evaluated at compile time. Thus, they add no overhead whatsoever during the execution of the program.
The function is the following:
template<class T>
inline T &instance() {
static T instance;
return instance;
}
That's it: it creates and returns a reference of an instance of the object. That reference is only created once, upon the first invocation of this function. The instance lives wth the application, and is automatically dereferenced before quitting the application. Thus, the destructor is properly called. Any invocation of the function for a given class will return the same instance of that class.
As the function is inlined, a good compiler should take that hint and limit the generated code to a simple return of the reference address.
Second part: the class.
We have a function that retuns us an instance of the class, but we are the to adapt the class to use the function. We need to lock the class against unwanted instantiations. Both the constructor and the destructor should be private or protected. And as we do it, we shuld say that instance<MyClass<>
is a friend of the class.
class Game {
public:
void run() {};
friend Game &(instance<Game>)();
private:
Game() {};
~Game() {};
};
By making the constructor and the destructor protected, we invalidate any instantiations of the class thet does not come from any friend functions or classes. As the only friend function that we allow to instatiate objects is our template function, we are sure that only through our instance retriever an object of such class can be held.
So that's it, no inheritance and no pesky virtual tables or map dereferences.
Making life easier
One can now get a reference of the global object and run a method there by saying:
instance<Game>().run();
That is prone to errors and tedious to write, is it not?
What about defining a function to retrieve our code? An inline function takes no more time to execute than a preprocessor macro, and still allows us type checking.
inline Game &
the_game() {
return instance<Game>();
}
Now we may invoke the run
method with:
the_game().run();
You may opt to go one step further and emulate a global variable, without parenthesis:
#define the_game (instance<Game>())
And the invocation will be as simple as:
the_game.run();
I still use the parenthesis.
Comments are, of course, appreciated.