Singleton pattern is one of the fundamental design patterns used in OOP. The traditional way of implementing this is by making the constructor's private and providing a static member that can create the instance - Meyers singleton implementation. This is an implementation of the singleton pattern utility in c++ by inheritance, which imposes the pattern on the classes that derive from it. Any attempt to create the singleton class causes compilation error.
The implementation can be found here. It needs C++11 support for smart pointers , thread safety and variadic templates.
A single instance of the class is created and shared using smart pointers with the public static member. The singleton candidate is made non copyable so that multiple instances don't exist on copy by making the copy constructors private. In order to avoid the single state of the singleton candidate throughout the life time of the application, a weak pointer is used to store the instance. A shared pointer can be used if a global instance is desired. A tag is created for every singleton candidate which is accessible only to the singleton candidate, which prevents its creation from outside the utility class. It provides support for any signature of the singleton candidate constructor with the help of variadic templates.
The singleton candidate is expected to inherit from the utility class publicly and accept the tag as the first parameter in its constructors, which can be passed only by the utility class.
A sample singleton candidate is shown below.
The implementation can be found here. It needs C++11 support for smart pointers , thread safety and variadic templates.
A single instance of the class is created and shared using smart pointers with the public static member. The singleton candidate is made non copyable so that multiple instances don't exist on copy by making the copy constructors private. In order to avoid the single state of the singleton candidate throughout the life time of the application, a weak pointer is used to store the instance. A shared pointer can be used if a global instance is desired. A tag is created for every singleton candidate which is accessible only to the singleton candidate, which prevents its creation from outside the utility class. It provides support for any signature of the singleton candidate constructor with the help of variadic templates.
The singleton candidate is expected to inherit from the utility class publicly and accept the tag as the first parameter in its constructors, which can be passed only by the utility class.
A sample singleton candidate is shown below.
#include<MySingleton.hpp>
class CSingletonCandidate : public CSingleton<CSingletonCandidate>
{
private:
int val;
public:
CSingletonCandidate(CSingletonTag<CSingletonCandidate>::TYPE tag, int v) :
CSingleton(tag),
val(v)
{
}
};
CSingletonCandidate::Type_T singleInstance = CSingletonCandidate::GetInstance<>(1);
This pattern is considered evil in some of the use cases and should be used cautiously. Singleton classes can also be used as a base class and the implementation of singletons should preserve the pattern even after being inherited and optionally allow multiple instances of the derived classes. This implementation is strictly singleton and cannot be base class. It can be tweaked to support derived class in which case the base class/ singleton candidate is not strictly singleton and the derived classes can create its instances. The derived classes can further be singletons by using the utility class.
The caveat is that the singleton candidate itself can create loopholes to tarnish the singleton pattern.