Registrar dinamicamente métodos construtores em um AbstractFactory em tempo de compilação usando modelos C ++

Ao implementar uma classe MessageFactory para instanciar objetos Message, usei algo como:

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

Isso funciona bem, mas toda vez que adiciono uma nova mensagem, tenho que adicionar um novo XXX_MSG e modificar a instrução switch.

Após algumas pesquisas, encontrei uma maneira de atualizar dinamicamente o MessageFactory em tempo de compilação, para que eu possa adicionar quantas mensagens desejar sem precisar modificar o próprio MessageFactory. Isso permite um código mais limpo e fácil de manter, pois não preciso modificar três locais diferentes para adicionar / remover classes de mensagens:

#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;                                                                                                                                                                                  
} 

O modelo aqui faz a mágica registrando-se na classe MessageFactory, todas as novas classes de mensagem (por exemplo, PingMessage e PongMessage) que subclasses de MessageTmpl.

Isso funciona muito bem e simplifica a manutenção do código, mas ainda tenho algumas perguntas sobre essa técnica:

Essa é uma técnica / padrão conhecido? qual é o nome? Quero pesquisar mais informações sobre isso.

Eu quero fazer a matriz para armazenar novos construtoresMessageFactory :: m_List [65536] um std :: map, mas isso faz com que o programa segfault antes mesmo de chegar a main (). Criar uma matriz de 65536 elementos é um exagero, mas não encontrei uma maneira de fazer deste um contêiner dinâmico.

Para todas as classes de mensagem que são subclasses de MessageTmpl, tenho que implementar o construtor. Caso contrário, ele não será registrado no MessageFactory.

Por exemplo, comentando o construtor do PongMessage:

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

resultaria no fato de a classe PongMessage não ser registrada pelo MessageFactory e o programa seria segfault noMessageFactory :: Create (11) linha. A questão é
por que a turma não se registra? Ter que adicionar a implementação vazia das mais de 100 mensagens que eu preciso parece ineficiente e desnecessário.

questionAnswers(7)

yourAnswerToTheQuestion