Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A Singleton that is not globally accessible

I just wondered what the best way is to get rid of the globally available static getInstance() in a Singleton. I do not want my Singleton classes being accessed from every point in my program.

I thought about maybe having a create() public static function that creates one object and returns it but one cannot call this method twice.

But it's not very elegant for me. Than I would have to make an assertion or throw an exception in case create() gets called a second time.

Is there any other way I can achieve what I want?

like image 656
tyrondis Avatar asked Dec 05 '25 07:12

tyrondis


1 Answers

You said that "creating one a second time would damage the whole application.". My response is: so don't make more then one. In C++, the type system is too weak to easily ensure this at compile-time. We can still write up a utility to approximate it at run-time, though.

Note, though, that this in no way implies you should use a singleton. (You have zero need for a global; it's unfortunate the drones have associated single-instance with global). What you want is this:

#include <stdexcept>

// inherit from this class (privately) to ensure only
// a single instance of the derived class is created
template <typename D> // CRTP (to give each instantiation its own flag)
class single_instance
{
protected: // protected constructors to ensure this is used as a mixin
    single_instance()
    {
        if (mConstructed)
            throw std::runtime_error("already created");

        mConstructed = true;
    }

    ~single_instance()
    {
        mConstructed = false;
    }

private:
    // private and not defined in order to
    // force the derived class be noncopyable
    single_instance(const single_instance&);
    single_instance& operator=(const single_instance&);

    static bool mConstructed;
};

template <typename T>
bool single_instance<T>::mConstructed = false;

Now you get an exception if the class is constructed more than once:

class my_class : private single_instance<my_class>
{
public:
    // usual interface (nonycopyable)
};

int main()
{
    my_class a; // okay
    my_class b; // exception
}
like image 189
GManNickG Avatar answered Dec 07 '25 19:12

GManNickG