Reputation: 77
Ok, I should simply tell that I want to make a base Singleton class that I can inherit from, and the way I want to achieve that is by a template.
In order to avoid memory leaks, I do not use directly a pointer to the instance, but a private class that will handle deleting the pointer.
Here is my actual code (not working) :
template <typename T> class Singleton
{
private:
class PointerInstance
{
private:
T* instance;
public:
PointerInstance() : instance(0) {}
~PointerInstance() { delete instance; } // no memory leak !
T* Get()
{
if ( !instance ) {
instance = new T();
}
return instance;
}
};
static PointerInstance PInstance;
public:
static T* pGetInstance(void)
{
return PInstance.pGet();
};
protected:
Singleton(void){};
~Singleton(void){};
};
And here is what a typical derived class declaration should look like :
class Child : public Singleton<Child>
{
friend class Singleton<Child>;
Child();
// etc...
};
Basically what is lacking is the instance of PInstance for each T class I make as a Singleton.
My question is : is there a way to do this once and for all with a few generic lines of code in the Singleton.h containing the code above, or do I have no other choice but to add a few specific lines of code for each derived class ?
(Bonus : is there a better way to do a Singleton class in C++ ?)
Upvotes: 3
Views: 1333
Reputation: 31455
First in general I would suggest you avoid using singletons where possible. They are horribly overused.
If you have to use them, I really do not get this new popular way (must have appeared in a journal somewhere because I see everyone using it now) of deriving from Singleton. Doing this causes as many problems as it solves.
If you have to have one though, the best way to initialise it is to use boost::once. You need to do something like this in your source where Foo is your class.
these 3 are all statically declared in Foo and private
Foo* Foo::instance = NULL;
boost::once_flag Foo::flag = BOOST_ONCE_INIT;
void Foo::init()
{
Foo::instance = new Foo;
};
This is also static and is the public method to get the instance
Foo & Foo::getInstance()
{
boost::call_once(init, Foo::flag);
return *Foo::instance;
}
The constructor of Foo must not throw.
Note that this technique can be used more extensively for thread-safe once-loading lazy-evaluation situations, not just singletons. The new version of boost::once takes first the flag (which is now a struct: beware) and secondarily takes a boost::function so you can boost::bind in information for creation.
For deleting your singleton, you can create a boost::shared_ptr at compilation unit level and bind your pointer to it, and use a custom deleter that is a static member of your class so that delete can remain private. Your deleter will be able to call delete though, and your init function will have access to the deleter function (which is also private) to initialise the shared_ptr with it.
Upvotes: 0
Reputation: 11833
Maybe you want to take a look at Loki which already has a generic SingletonHolder<>
class?
Upvotes: 0
Reputation: 15808
Here is a simpler way of writing a CRTP Singleton without a memory leak:
template <class T>
class Singleton
{
friend class T;
private:
Singleton() {};
~Singleton() {};
Singleton(const Singleton&); // not implemented
const Singleton& operator=(const Singleton&); // not implemented
public:
static T* pGetInstance()
{
static T theInstance;
return &theInstance;
}
};
Usage is the same as in the question.
Upvotes: 2
Reputation: 507423
template <typename T>
typename Singleton<T>::PointerInstance Singleton<T>::PInstance;
In the header outside of the classes. Note that whatever you write in PInstance
's default constructor, the code will never be executed if you never call pGetInstance
or never refer to PInstance
in another way from non-template code. But that should be fine.
Upvotes: 5