Ivan Čukić

Singletons, shared instances, the modern way

The last post showed how to create a modern and safe d-ptr (pimpl) idiom. There were a few questions regarding the purpose of such a thing, when you can directly use std::unique_ptr or QScopedPointer. The main reason is that it provides additional safeguards from abuse by making the interface minimal. Most importantly, it does not provide an interface to get the raw pointer. (note: it does, but if you are able and want to write something like delete d.operator->() who am I to stop you)

Today, we’ll talk about something evil – singletons. Or, more precisely, the lesser evil brother of a singleton that lasts only while someone holds a pointer to it. Again, it is not something that is difficult to implement, even in old C++, but thanks to the new smart pointers of C++11 it starts to be more elegant.

template <typename Target>
class shared_singleton {
public:
    static std::shared_ptr<Target> instance()
    {
        auto ptr = s_instance.lock();
 
        if (!ptr) {
            ptr = std::make_shared<Target>();
            s_instance = ptr;
        }
 
        return ptr;
    }
 
private:
    static std::weak_ptr<Target> s_instance;
};
 
template <typename Target>
std::weak_ptr<Target> shared_singleton<Target>::s_instance;

There’s room for improvement (thread safety, interface), but it works quite well as it is.

And yes, I’m aware that it can be done with Qt’s pointer classes, or QShared* ones. :)

Loading comments...