title: Dynamically register constructor methods in an AbstractFactory at compile time using C++ templates
body: <p>When implementing a MessageFactory class to instatiate Message objects I used something like:</p>
  
  <pre><code>class MessageFactory 
  {
    public:
      static Message *create(int type)
      {
         switch(type) {
           case PING_MSG:
              return new PingMessage();
           case PONG_MSG:
              return new PongMessage();
           ....
      }
  }
  </code></pre>
  
  <p>This works ok but every time I add a new message I have to add a new XXX_MSG and modify the switch statement.</p>
  
  <p>After some research I found a way to dynamically update the MessageFactory at compile time so I can add as many messages as I want without need to modify the MessageFactory itself. This allows for cleaner and easier to maintain code as I do not need to modify three different places to add/remove message classes:</p>
  
  <pre><code>#include &lt;stdio.h&gt;                                                                                                                                                                           
  #include &lt;stdlib.h&gt;                                                                                                                                                                          
  #include &lt;string.h&gt;                                                                                                                                                                          
  #include &lt;inttypes.h&gt;                                                                                                                                                                        
  
  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&lt;int TYPE, typename IMPL&gt;                                                                                                                                                            
  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 &lt;int TYPE, typename IMPL&gt;                                                                                                                                                           
  const uint16_t MessageTmpl&lt;TYPE, IMPL &gt;::MESSAGE_ID = MessageFactory::Register(                                                                                                              
       MessageTmpl&lt;TYPE, IMPL &gt;::_MESSAGE_ID, &amp;MessageTmpl&lt;TYPE, IMPL &gt;::Create);                                                                                                              
  
  class PingMessage: public MessageTmpl &lt; 10, PingMessage &gt;                                                                                                                                    
  {⋅                                                                                                                                                                                           
    public:                                                                                                                                                                                    
    PingMessage() {}                                                                                                                                                                           
    virtual void say() { printf("Ping\n"); }                                                                                                                                                   
  };                                                                                                                                                                                           
  
  class PongMessage: public MessageTmpl &lt; 11, PongMessage &gt;                                                                                                                                    
  {⋅                                                                                                                                                                                           
    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-&gt;say();                                                                                                                                                                               
  
    msg2 = MessageFactory::Create(11);                                                                                                                                                         
    msg2-&gt;say();                                                                                                                                                                               
  
    delete msg1;                                                                                                                                                                               
    delete msg2;                                                                                                                                                                               
  
    return 0;                                                                                                                                                                                  
  } 
  </code></pre>
  
  <p>The template here does the magic by registering into the MessageFactory class, all new Message classes (e.g. PingMessage and PongMessage) that subclass from MessageTmpl.</p>
  
  <p>This works great and simplifies code maintenance but I still have some questions about this technique:</p>
  
  <ol>
  <li><p>Is this a known technique/pattern? what is the name? I want to search more info
  about it.</p></li>
  <li><p>I want to make the array for storing new constructors <strong>MessageFactory::m_List[65536]</strong> 
  a std::map but doing so causes the program to segfault even before reaching main().
  Creating an array of 65536 elements is overkill but I have not found a way to 
  make this a dynamic container.</p></li>
  <li><p>For all message classes that are subclasses of MessageTmpl I have to implement
  the constructor. If not it won't register in the MessageFactory.</p>
  
  <p>For example commenting the constructor of the PongMessage:</p>
  
  <pre><code> class PongMessage: public MessageTmpl &lt; 11, PongMessage &gt;       
   {                                                                                                                                                                                           
     public:                                                                                                                                                                                    
      //PongMessage() {} /* HERE */                                                                                                                                                                          
      virtual void say() { printf("Pong\n"); }                   
   };
  </code></pre>
  
  <p>would result in the PongMessage class not being registered by the MessageFactory and the
  program would segfault in the <strong>MessageFactory::Create(11)</strong> line. The question is<br>
  why the class won't register? Having to add the empty implementation of the 100+ 
  messages I need feels inefficient and unnecessary.   </p></li>
  </ol>