I need to define a singleton class in C++ that is implemented separately across different platforms. (e.g. macOS, Windows, Linux, etc.) In case it matters, this is for a Qt application and the singleton will be inheriting from QObject
.
I could do this simply using some preprocessor directives and including totally separate implementations, like so:
// Singleton.h
#include <QtGlobal>
#if defined Q_OS_WIN
#include "Singleton_win.h"
#elif defined Q_OS_MAC
#include "Singleton_mac.h"
#elif ... etc ...
#endif
However, for my own planning and sanity I'd love it if there was a way I could define what actual methods need to be implemented across all platforms so that the different implementations can stay at least partially synchronized.
If I were programming in a language with interfaces, I would handle this just by defining an interface and having each platform-specific version of the singleton implement it.
However, this is C++, and the closest I have to an interface is an abstract base class. But using an abstract base class is troublesome. I need a static method on whatever the singleton is for getting the global instance of that singleton, and of course C++ doesn't allow abstract static methods. I can't use a templated static method that returns the right implementation of the singleton because everywhere else in my code that uses the singleton doesn't and shouldn't know which implementation it's going to use.
Lastly, I'd really like to avoid any patterns that involve an excessive amount of boilerplate code. One such pattern I feel could be used to create this Singleton but qualifies as involving excessive boilerplate is the PImpl pattern, because it would require me doing something like this:
// Singleton.h
class Singleton {
public:
Singleton();
~Singleton();
static Singleton * shared() { static Singleton s; return &s; };
void publicMethodA();
void publicMethodB();
// etc.
protected:
class impl;
impl *p;
}
// Singleton.cpp
class Singleton::impl {
public:
void publicMethodA();
void publicMethodB();
// etc.
}
void Singleton::impl::publicMethodA() {
// actual publicMethodA implementation here
}
void Singleton::impl::publicMethodB() {
// actual publicMethodB implementation here
}
// further public methods implemented here
// Singleton constructors and destructors implemented here
void Singleton::publicMethodA() {
impl->publicMethodA();
}
void Singleton::publicMethodB() {
impl->publicMethodB();
}
// further boilerplate for Singleton's public methods implemented here
Basically my gripe is that for every public method on Singleton
that I write, I have to add a method that calls through to another method with an identical signature on Singleton::impl
. This is just my personal preference, but I can't stand boilerplate code like that! I'd really like to avoid it.
Furthermore, once we consider that this is going to be a QObject
-inherited class with Qt signals, slots, and possibly properties, having an Singleton::impl
will introduce further complexities because it's Singleton
that needs to be emitting signals and receiving connections from other QObjects
.
So given that, are there any patterns I can use that allow me to implement this singleton the way I'm looking to do?