Making a singleton of a global pointer with minimal work
I have discovered a way to make a global pointer accessible in a safe way,
that dosn't involve making lots of code changes. For example, let's say
that there is a class called _GHAL (from our code base) and that there is a
global pointer to the only instance of this class:
_GHAL* GHAL; // initialized as part of some startup code
Users of this class assume that the pointer actually points to an instance
of _GHAL. As you know, static initialization order can not be determined,
so if there are other classes using the GHAL pointer as part of their
initialization, we are in trouble. Now, it's quite easy to make _GHAL a
singleton class. Make the constructor private, as well as copy constructor
and assignment operator. Allow access only through static Instance method:
_GHAL& operator=(const _GHAL&);
static _GHAL& Instance(); // singleton point of access
Now, everyone using _GHAL has to write _GHAL::Instance().Method(...). This
is much better, but what if you don't know all the places the GHAL pointer
is actually used? There might be libraries using GHAL that you normally
don't compile. There are going to be compilation errors that other people
will have to fix, which is not a very nice thing to do. Well, I have found
a workaround that doesn't require any changes except to the _GHAL class and
to the global GHAL pointer. Let's have a look.
We need to change the GHAL pointer so that it works just like a _GHAL
pointer, but actually uses _GHAL as a singleton. What we do is to create a
new class, and overload operator->:
_GHAL* operator->() const;
// Singleton point of access
static GHAL_ptr& Instance();
GHAL_ptr& operator=(const GHAL_ptr&);
This class is a singleton and we let the only instance be named GHAL.
extern GHAL_ptr& GHAL; // in a headerfile
Let's look at the implementation.
// operator-> returns a pointer to the only _GHAL instance
_GHAL* GHAL_ptr::operator->() const
static _GHAL* theGHAL = &_GHAL::Instance();
// GHAL_ptr singleton access
static GHAL_ptr theGHAL_ptr;
// initialize the global GHAL variable to the only GHAL_ptr instance
GHAL_ptr& GHAL = GHAL_ptr::Instance();
That's it! All those GHAL-> uses that might be littered all over the code
base will now be safe. No other code changes are required. Now we can
change all those GHAL-> into _GHAL::Instance() little by little, which is a
nice thing to do, I believe.
I hope this was interesting for someone! Comments are welcome.
P.S. Followup set to m.p.v.l because I can only post there.