Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Singleton template class inheritance

I have an abstract Singleton class. My goal is that any subclasses just have to implement the init() function AND NOTHING ELSE. Here is what I did:

template <typename T>
class Singleton
{
    public: 

        Singleton()
        {
            init();
        }

        static T& instance()
        {
            static T instance;
            return instance;
        }

    protected:
        virtual void init() = 0;   
};

class SubSingleton : public Singleton<SubSingleton>
{
    protected: 
        void init()
        {
            cout << "Init SubSingleton" << endl;
        }
};

This won't compile, since init() is protected and can't be called from a public static function. There are 2 solutions to this problem. First we can make the init() function public, but I don't want to expose this function publicly. So this only leaves the second solution, change the subclass as follows:

class SubSingleton : public Singleton<SubSingleton>
{
    friend class Singleton<SubSingleton>;

    protected:

        void init()
        {
            cout << "Init SubSingleton" << endl;
        }
};

This works perfectly, but I don't want the friend statement, since other programmers might extend my code and might not know that this should be added.

Is there any other way of implementing this without the friend statement? Maybe anything from Andrei Alexandrescu?

EDIT: The init function is now called in the constructor instead of the instance() function.

EDIT2: For technical reasons and compatibility I need an init() function and can't just do the initialization in the constructor.

The solution for casting works, but if I call init() from the constructor the casting doesn't work anymore. Any suggestions?

like image 311
goocreations Avatar asked Feb 20 '23 22:02

goocreations


1 Answers

You do not need this init() stuff at all. It only makes problems here.

template <typename T>
class Singleton
{
    public: 
        static T& instance()
        {
            static T instance;
            return instance;
        }
};

class SubSingleton : public Singleton<SubSingleton>
{
    public: 
        SubSingleton()
        {
            cout << "Init SubSingleton" << endl;
        }
};

In this way you not only remove unnecessary stuff - but you also prevent from calling init() every time someone calls instanse()...

like image 112
PiotrNycz Avatar answered Mar 05 '23 10:03

PiotrNycz