Search code examples
c++singletoncode-separation

Multiple Singleton Instances


I am writing a library of utility classes, many of which are singletons. I have implemented them as such using inheritance:

template <class T>
class Singleton {
    public:
        T& getInstance() {
            if(m_instance == 0) {
                 m_instance = new T;
            }

            return m_instance;
        }
    private:
        static T* m_instance;
};

class SomeClass : public Singleton<SomeClass> {
    public:
        SomeClass() {}
        virtual ~SomeClass() {}

        void doSomething() {;}
};

Obviously this is a simple example, not an actual class. Anyways, I am finding that using code such as:

SomeClass::getInstance().doSomething();

Will create more than one instance of SomeClass. I am thinking this may be due to the fact that it is being used outside my library (.a) file as well as internally. For example, I am using a UI library not written by myself which is separately compiled and to which I am making additions. Some of these additions utilize singletons which are also being used in my .a library.

Is the separate compilation causing this? Something else?

The only way I have managed to get around the issue is to create a global object in my main.cpp file which I initialize with any singletons I will need. Then all code accesses this common global object with calls such as:

GlobalObject::getSomeClass().doSomething()

I hate having to add an additional method to this object every time I create another singleton. Plus the syntax seems clearer and more familiar using the first access method:

SomeClass::getInstance().doSomething();

Please let me know if you have any thoughts, opinions, etc.

Thanks.


Solution

  • Your problem is that your template is going to be instantiated in more than one compilation unit as it is completely inline. Therefore in every compilation unit that uses the template you will end up creating one singleton (per compilation unit). What you would need is to force global linkage, so that all compilation units reference the same template instantiation. The upcoming C++ standard will support this via extern template. What you can do now is to disable automatic instantiation in your project and manually instantiate the templates that you use explicitly. This way when you use the template in any compilation unit you will generate an unknown reference to the implementation which can then be satisfied by the linker from the (one) compilation unit where you do the explicit instantiation.