How can I inherit a magic static singleton?

54 views Asked by At

I would like to inherit from a magic static singleton in a derived:

#include <iostream>

int main();

class SingletonBase{
protected:
    int i=0;
    SingletonBase(int){}
    //
    friend int main();
    static void show(){
        static SingletonBase s(2); // this is sometimes referred to as the "magic static singleton pattern"
        s.i++;
        std::cout << "SingletonBase::i="<<s.i<<"\n";
    }
};

class Singleton: public SingletonBase{
private:
    Singleton(int):SingletonBase(int{}){}
    int j=0; // unfortunately, Singleton has data, too.
public:
    static void show(){
        static Singleton s(3);
        s.i++;
        s.j++;
        std::cout << "Singleton::SingletonBase::i="<<s.i<<". Singleton::j="<<s.j<<"\n";
    }
    //
};

int main() {
    Singleton::show();
    Singleton::show();
    Singleton::show();
    Singleton::show();
    SingletonBase::show();
    SingletonBase::show();
    SingletonBase::show();
    Singleton::show();
    Singleton::show();
    Singleton::show();
    Singleton::show();
}

The output is:

Singleton::SingletonBase::i=1. Singleton::j=1
Singleton::SingletonBase::i=2. Singleton::j=2
Singleton::SingletonBase::i=3. Singleton::j=3
Singleton::SingletonBase::i=4. Singleton::j=4
SingletonBase::i=1
SingletonBase::i=2
SingletonBase::i=3
Singleton::SingletonBase::i=5. Singleton::j=5
Singleton::SingletonBase::i=6. Singleton::j=6
Singleton::SingletonBase::i=7. Singleton::j=7
Singleton::SingletonBase::i=8. Singleton::j=8

But what I expected (and need) is for i to increase by 1 in each output line. That is, the Singleton (there is supposed to be only one) shall inherit the SingletonBase.

How can this be done?

Remark

I cannot unfriend main.

The application context is that I have two distinct types template<typename T>ElementA and template<typename T>ElementB with much mutual functionality. So I inherit both from a template<typename T>ElementBase. Both are putting stuff on a StackA<T> and StackB<T>, respectively, that share a lot functionality in turn. So I inherit both stacks from StackBase<T>. In the above example, main is the ElementBase calling upon SingletonBase; and SingletonBase in turn is StackBase, since being the base of Singleton, which models StackA / StackB.

Unfriending main means ElementBase<T> cannot push into StackBase<T>, meaning I'd have to implement everything for A and B redundantly.

1

There are 1 answers

0
GRamon On

Warning: Ugly.

#include <iostream>

int main();

class SingletonBase{
private:
    int i=0;
    SingletonBase(int){}
    //
    friend int main();
    friend class Singleton;
protected:
    static SingletonBase& Instance(){
        static SingletonBase s(int{});
        return s;
    }
    static void show(){
        std::cout << "SingletonBase::i="<< Instance().i++ << "\n";
    }
};

class Singleton{
private:
    Singleton(int){}
    SingletonBase* b;
public:
    //
    static Singleton& Instance(){
        static Singleton s(int{});
        s.b = &SingletonBase::Instance();
        return s;
    }
    static void show(){
        std::cout << "Singleton.SingletonBase->i="<< Instance().b->i++ << "\n";
    }
    //
};

int main() {
    SingletonBase::Instance().show();
    SingletonBase::Instance().show();
    Singleton::Instance().show();
    SingletonBase::Instance().show();
    Singleton::Instance().show();
    SingletonBase::Instance().show();
}

So the idea is to compose a static state of Singleton and its Base by use of a pointer to the base instead of inheriting it. Because the interface to the outside from both singletons is channelled through the Instance() function, the only risk remaining is with memory leaks within the implementation of Singleton (e.g. overwriting b).