Useful C++ template magic. Hiding nasty global static’s

In C++, often there is a need to provide and support single instance of certain class, accessible on demand from anywhere in the program. That is encyclopedic example given in many books promoting singleton pattern. For instance, if your program has a log file, it is strongly recommended that you make a class that encapsulates all logging and make it singleton. This approach, without any doubts, is much much better than making global static instance of the logger and then referring to it from whatever you need as it reduces number of cross-dependencies, an issue that stays among the most bad techniques making code less maintainable.

This is easy to understand – while there is nothing wrong in static variable, even in global static variable, we must ensure that it is initialized before it is used first, which is especially important if the object has to be created dynamically. And this is the problem Singleton pattern solves.

Take the example

// SomeSourceFile.h
#include "CoffeePlantation.h"
static CoffeePlantation g_Plantation;

// SomeSourceFile.cpp
#include "SomeSourceFile.h"
// Initialize the instance
g_Plantation = CoffeePlantation();

 Note: coffee plantation...
Note – coffee plantation object is created on a stack. Plantation’s constructor will be called before main() and, presumably, any other code that uses g_Plantation. But in order to use this single plantation, you’ll must include this “SomeSourceFile.h” into every file when it is or may be referred from. Moreover, once you added more global statics, you may get lost is you sources as you’ll need to keep in mind which header declares what variable. Having single common header file may help a little, though, but not always.

From the other hand, there are still heaps of cases when you’d rather use global static variable for certain need. For instance, pattern “State” (see “Design patterns” by GoF) assumes that all object represent states have to implement singleton pattern. But at the closer look you may realize that it makes code unnecessary complex and bulky – state machine of that kind assumes that all transitions and states are already known, they don’t change in runtime and can be created once-and-for-all, in other words, they must be static.

Right, how we handle this situation then?

Well, it’s about the time when “template” word, so many developers are still afraid of, should be addressed. C++ template is a great way to ask compiler to generate as many synthetic data types as we want exactly when we need them. For instance, vectorand vectorare two different data types. Which meaning does it have for our task?

Check this out:

// file name: StaticInstance.htemplate 
class  tStaticInstance
{
public:
        static T* GetInstance();
private:
        static T m_Instance;
}

template 
T tStaticInstance::m_Instance = T();

That’s it. That’s really all we need to hide ugly global static behind nice looking fence. Now, instead of declaring static variable in designated header and then pushing it *.h around the project, just do this:

#include "StaticInstance.h"/// somewhere somewhentStaticInstance::GetInstance()->SomeMethod();

tStaticInstance::GetInstance()->SomeMethod();

This code may look a bit scary, but it solves the whole bunch of problems:

  • There is no need to modify either of MyConcreteType or OtherType to implement singleton functionality they may not need generally.
  • Global static variable can be “created” from any place in your program without the need of declaring it anywhere else
  • Does not have singleton’s weaknesses
  • This expression clearly explains that in this particular place we wanted to deal with single global instance of the class. There are quite a few cases when it may be useful
  • Code is very simple
  • Static objects are created automatically and only if they are used. Unlike the case with implicit static declaration, it is now impossible to declare an object that is never used.

Of course, there is a price to pay:

  • The uniqueness of the instance is only guaranteed within single binary and we fully rely on modern compiler and linker
  • Object gets created once a construction with tStaticInstance::GetInstance() appears in the code, even if that code is never going to be used (which is quite bad by itself) or gets called once in a blue moon.

It is also not idiot-proof:

MyType pInstance* = tStaticInstance::GetInstance();

delete pInstance;     // Something bad happens here

That delete will lead to crash, but it will be trivial to track down and fix. You write unit test for you code, aren’t you?

I have been using this pattern in several projects and it works just fine, assuming that it is intended for occasions where your code is allowed to know that is deals with static instance of the class.

Having said that, this is how I would deal with my coffee plantation:

// CoffeeHarvester.h
#include "CoffeePlantation.h"
#include "StaticInstance.h"
// ...
tStaticInstance::GetInstance()->CheckIfCoffeeRipeEnough();

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

7 visitors online now
2 guests, 5 bots, 0 members
Max visitors today: 23 at 12:39 am UTC
This month: 57 at 04-16-2021 08:12 am UTC
This year: 57 at 04-16-2021 08:12 am UTC
All time: 332 at 11-22-2019 03:23 am UTC