I was hoping to use an interface to make a generic template class I can add to any other class to easily create singletons. (By easily create singletons I mean avoid having to re-write the 6 lines for GetInstance
)
template <class T>
class Singleton
{
public:
static T* GetInstance();
};
template<class T>
inline T* Singleton<T>::GetInstance()
{
static T* myInst;
if (!myInst)
{
myInst = new T();
}
return(myInst);
}
The only issue is that with this to work I have to have the constructor for the class be public, which I would like to avoid as it sort of ruins the Singleton design pattern.
Is there a solution I may not be aware of to get an instance for the generic type without having a public constructor? I do realise this might be a stupid question but I would really like this class to work.
Thanks
CodePudding user response:
First of all, your singleton should look differently as yours isn't thread safe. Then there are at least 2 solutions. First, is to make a particular instantiation a friend, so it would look something like this:
template <class T>
class Singleton
{
public:
static T* GetInstance();
};
template<class T>
T* Singleton<T>::GetInstance()
{
static T myInst;
return &myInst;
}
class Test
{
public:
void print()
{
std::cout << "Hello!\n";
}
private:
Test() = default;
friend class Singleton<Test>;
};
That would require the modification of the user class which isn't ideal. So we can employ another solution like this:
template <class T>
class Singleton: private T
{
public:
static T* GetInstance();
private:
using T::T;
};
template<class T>
T* Singleton<T>::GetInstance()
{
static Singleton<T> myInst;
return &myInst;
}
class Test
{
public:
void print()
{
std::cout << "Hello!\n";
}
protected:
Test() = default;
};
The only modification to the user class is making its ctor to be protected
instead of private
which is not a problem, in my opinion. The limitation is that the user class should not be final
.