jeudi 23 novembre 2023

How can I inherit a magic static singleton?

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.

Aucun commentaire:

Enregistrer un commentaire