Динамически регистрировать методы конструктора в AbstractFactory во время компиляции с использованием шаблонов C ++

При реализации класса MessageFactory для создания объектов Message я использовал что-то вроде:

class MessageFactory 
{
  public:
    static Message *create(int type)
    {
       switch(type) {
         case PING_MSG:
            return new PingMessage();
         case PONG_MSG:
            return new PongMessage();
         ....
    }
}

Это работает нормально, но каждый раз, когда я добавляю новое сообщение, мне нужно добавить новый XXX_MSG и изменить оператор switch.

После некоторых исследований я нашел способ динамически обновлять MessageFactory во время компиляции, чтобы я мог добавлять столько сообщений, сколько захочу, без необходимости изменять сам MessageFactory. Это позволяет чище и проще поддерживать код, так как мне не нужно изменять три разных места для добавления / удаления классов сообщений:

#include <stdio.h>                                                                                                                                                                           
#include <stdlib.h>                                                                                                                                                                          
#include <string.h>                                                                                                                                                                          
#include <inttypes.h>                                                                                                                                                                        

class Message                                                                                                                                                                                
{                                                                                                                                                                                            
   protected:                                                                                                                                                                                
      inline Message() {};                                                                                                                                                                   

   public:                                                                                                                                                                                   
      inline virtual ~Message() { }                                                                                                                                                          
      inline int getMessageType() const { return m_type; }                                                                                                                                   
      virtual void say() = 0;                                                                                                                                                                

   protected:                                                                                                                                                                                
      uint16_t m_type;                                                                                                                                                                       
};                                                                                                                                                                                           

template<int TYPE, typename IMPL>                                                                                                                                                            
class MessageTmpl: public Message                                                                                                                                                            
{                                                                                                                                                                                            
   enum { _MESSAGE_ID = TYPE };                                                                                                                                                              
   public:                                                                                                                                                                                   
      static Message* Create() { return new IMPL(); }                                                                                                                                        
      static const uint16_t MESSAGE_ID; // for registration                                                                                                                                  

   protected:                                                                                                                                                                                
      MessageTmpl() { m_type = MESSAGE_ID; } //use parameter to instanciate template                                                                                                         
};                                                                                                                                                                                           

typedef Message* (*t_pfFactory)();                                                                                                                                                           
class MessageFactory⋅                                                                                                                                                                        
{                                                                                                                                                                                            ,
   public:                                                                                                                                                                                   
     static uint16_t Register(uint16_t msgid, t_pfFactory factoryMethod)                                                                                                                     
     {                                                                                                                                                                                       
       printf("Registering constructor for msg id %d\n", msgid);                                                                                                                             
       m_List[msgid] = factoryMethod;                                                                                                                                                        
       return msgid;                                                                                                                                                                         
     }                                                                                                                                                                                       

     static Message *Create(uint16_t msgid)                                                                                                                                                  
     {                                                                                                                                                                                       
       return m_List[msgid]();                                                                                                                                                               
     }                                                                                                                                                                                       
     static t_pfFactory m_List[65536];                                                                                                                                                       
};  

template <int TYPE, typename IMPL>                                                                                                                                                           
const uint16_t MessageTmpl<TYPE, IMPL >::MESSAGE_ID = MessageFactory::Register(                                                                                                              
     MessageTmpl<TYPE, IMPL >::_MESSAGE_ID, &MessageTmpl<TYPE, IMPL >::Create);                                                                                                              

class PingMessage: public MessageTmpl < 10, PingMessage >                                                                                                                                    
{⋅                                                                                                                                                                                           
  public:                                                                                                                                                                                    
  PingMessage() {}                                                                                                                                                                           
  virtual void say() { printf("Ping\n"); }                                                                                                                                                   
};                                                                                                                                                                                           

class PongMessage: public MessageTmpl < 11, PongMessage >                                                                                                                                    
{⋅                                                                                                                                                                                           
  public:                                                                                                                                                                                    
  PongMessage() {}                                                                                                                                                                           
  virtual void say() { printf("Pong\n"); }                                                                                                                                                   
};                                                                                                                                                                                           

t_pfFactory MessageFactory::m_List[65536];                                                                                                                                                   

int main(int argc, char **argv)                                                                                                                                                              
{                                                                                                                                                                                            
  Message *msg1;                                                                                                                                                                             
  Message *msg2;                                                                                                                                                                             

  msg1 = MessageFactory::Create(10);                                                                                                                                                         
  msg1->say();                                                                                                                                                                               

  msg2 = MessageFactory::Create(11);                                                                                                                                                         
  msg2->say();                                                                                                                                                                               

  delete msg1;                                                                                                                                                                               
  delete msg2;                                                                                                                                                                               

  return 0;                                                                                                                                                                                  
} 

Шаблон здесь делает волшебство, регистрируясь в классе MessageFactory, все новые классы сообщения (например, PingMessage и PongMessage), которые подкласс от MessageTmpl.

Это прекрасно работает и упрощает обслуживание кода, но у меня все еще есть некоторые вопросы по поводу этой техники:

Это известная техника / шаблон? Как тебя зовут? Я хочу найти больше информации об этом.

Я хочу сделать массив для хранения новых конструкторовMessageFactory :: m_List [65536] std :: map, но при этом программа вызывает segfault даже до достижения main (). Создание массива из 65536 элементов является излишним, но я не нашел способа сделать это динамическим контейнером.

Для всех классов сообщений, которые являются подклассами MessageTmpl, я должен реализовать конструктор. Если нет, он не будет зарегистрирован в MessageFactory.

Например, комментируя конструктор PongMessage:

 class PongMessage: public MessageTmpl < 11, PongMessage >       
 {                                                                                                                                                                                           
   public:                                                                                                                                                                                    
    //PongMessage() {} /* HERE */                                                                                                                                                                          
    virtual void say() { printf("Pong\n"); }                   
 };

приведет к тому, что класс PongMessage не будет зарегистрирован в MessageFactory, и программа перестанет работать вMessageFactory :: Create (11) линия. Вопрос в том
почему класс не регистрируется? Необходимость добавить пустую реализацию из 100+ нужных мне сообщений кажется неэффективной и ненужной.

Ответы на вопрос(7)

Ваш ответ на вопрос