Best way to for C++ types to self register in a list?

前端 未结 4 1369
不思量自难忘°
不思量自难忘° 2020-12-03 08:33

Suppose I have some per-class data: (AandB.h)

class A
{
public:
   static Persister* getPersister();
}

class B
{
public:
   static Persister* getPersister()         


        
4条回答
  •  清歌不尽
    2020-12-03 09:31

    Register each template at run-time in the constructor. Use a static variable per template to check if the type has already been registered. The following is a quickly hacked together example:

    #include 
    #include 
    
    using namespace std;
    
    class Registerable {
        static vector registry_;
    
    public:
        static void registerFoo(Registerable *p)
        {
            registry_.push_back(p);
        }
    
        static void printAll()
        {
            for (vector::iterator it = registry_.begin();
                 it != registry_.end(); ++it)
                (*it)->print();
        }
    
        virtual void print() = 0;
    };
    
    vector Registerable::registry_;
    
    template 
    class Foo : public Registerable {
        static bool registered_;
    
    public:
        Foo()
        {
            if (!registered_) {
                registerFoo(this);
                registered_ = true;
            }
        }
    
        void print()
        {
            cout << sizeof (T) << endl;
        }
    };
    
    template  bool Foo::registered_ = false;
    
    int
    main(int argc, char *argv[])
    {
        Foo fooChar;
        Foo fooShort;
        Foo fooInt;
    
        Registerable::printAll();
    
        return 0;
    }
    

    It should output the size of each template parameter in the order the classes were instantiated:

    1
    2
    4
    

    This version removes the registration code from each constructor and puts it in a base class.

    #include 
    #include 
    
    using namespace std;
    
    class Registerable {
        static vector registry_;
    
    public:
        static void registerFoo(Registerable *p)
        {
            registry_.push_back(p);
        }
    
        static void printAll()
        {
            for (vector::iterator it = registry_.begin();
                 it != registry_.end(); ++it)
                (*it)->print();
        }
    
        virtual void print() = 0;
    };
    
    vector Registerable::registry_;
    
    template 
    class Registerer : public Registerable {
        static bool registered_;
    
    public:
        Registerer(T *self)
        {
            if (!registered_) {
                registerFoo(self);
                registered_ = true;
            }
        }
    };
    
    template  bool Registerer::registered_ = false;
    
    template 
    class Foo : public Registerer > {
    public:
        Foo() : Registerer >(this) { }
    
        void print()
        {
            cout << sizeof (T) << endl;
        }
    };
    
    int
    main(int argc, char *argv[])
    {
        Foo fooChar;
        Foo fooShort;
        Foo fooInt;
    
        Registerable::printAll();
    
        return 0;
    }
    

    I added an example of another non-template class using the registry. So, the final output would be:

    foo: 1
    foo: 2
    foo: 4
    bar
    

提交回复
热议问题