Reputation: 1899
I'm currently working on an application which heavily uses Singletons and Dynamic Libraries (using dlopen).
My problem is that the instance of my Singleton within the application AND within the dynamic library is different (i.e in my implementation, the Singleton::getInstance method returns a different address)
This is how I define a Singleton
// Singleton.hpp
template<typename T>
class Singleton
{
static T *_instance;
protected:
Singleton<T>() {}
virtual ~Singleton<T>() {}
public:
static T *getInstance() {
if (_instance == NULL)
_instance = new T;
return (_instance);
}
static void deleteInstance() {
if (_instance) {
delete _instance;
_instance = NULL;
}
}
};
template<typename T>
T *Singleton<T>::_instance = NULL;
Then, if I want a class Test to be a Singleton, I need to do :
// Test.hh
#include "Singleton.hpp"
class Test : public Singleton<Test>
{
friend class Singleton<Test>;
private:
Test();
public:
virtual ~Test();
void doSomeStuff();
};
Now if I want to use Test, I do :
#include "Test.hh"
int main() {
Test *test = Test::getInstance();
test->doSomeStuff();
return (0);
}
To solve the problem, I tried to somehow " extern " (using the keyword) the static class member Singleton::_instance, but I never succeeded in compiling my application ... GCC refuses that kind of code (in the Singleton.hpp) file :
template<typename T>
extern T *Singleton<T>::_instance;
Upvotes: 0
Views: 147
Reputation: 4450
The following needs to be moved out of singleton.hpp. As written it creates an instance of the pointer for each .cpp file that includes singleton.hpp.
template<typename T>
T *Singleton<T>::_instance = NULL;
Remember that this is a definition, not a declaration. So every object file that includes your header is now defining Singleton::_instance. If multiple .cpp files include singleton.h and instantiate the template with the same type in a single target (executable or library) you'll get multiply defined symbols.
To make this code correct you'll need to pick a single .cpp file (in the client of the singleton template) and defined _instance there. This is obviously not super desirable, so consider not using a singleton (your first, best option) or using a different singleton pattern.
Upvotes: 1