title: Store different templated classes in one container without losing information about it's type
body: <p>I'm currently working on a project where a client part of my application has to be able to create custom templated classes on the server. The server part has to keep track of these created classes and has to remember the types with which the classes has been instantiated. The problem is, that there are around 36 different class-template-combinations that are valid in my application. I'm currently struggling to keep track of these different types in a collection without losing information about my instances.</p>
  
  <p>I'm currently using something like this:</p>
  
  <pre><code>#include &lt;memory&gt;
  #include &lt;type_traits&gt;
  #include &lt;vector&gt;
  
  enum class data_type : std::uint8_t {
      type_int = 1,
      type_float,
      type_double
  };
  
  enum class class_type : std:: uint8_t {
      type_A = 1,
      type_B
  };
  
  struct X {
      virtual data_type get_data_type() = 0;
      virtual class_type get_class_type() = 0;
  };
  
  template &lt;typename T&gt;
  struct A : X {
      data_type get_data_type() override
      {
          if (std::is_same&lt;T, int&gt;::value) {
              return data_type::type_int;
          } else if (std::is_same&lt;T, float&gt;::value) {
              return data_type::type_float;
          } else if (std::is_same&lt;T, double&gt;::value) {
              return data_type::type_double;
          } else {
              /* ... */
          }
      }
  
      class_type get_class_type() override
      {
          return class_type::type_A;
      }
  };
  
  template &lt;typename T&gt;
  struct B : X {
      data_type get_data_type() override
      {
          if (std::is_same&lt;T, int&gt;::value) {
              return data_type::type_int;
          } else if (std::is_same&lt;T, float&gt;::value) {
              return data_type::type_float;
          } else if (std::is_same&lt;T, double&gt;::value) {
              return data_type::type_double;
          } else {
              /* ... */
          }
      }
  
      class_type get_class_type() override
      {
          return class_type::type_B;
      }
  };
  
  struct Storage {
  
      template &lt;typename T, template &lt;typename&gt; class Class&gt;
      void create() {
          Class&lt;T&gt;* t = new Class&lt;T&gt;();
          _classes.push_back(std::unique_ptr&lt;X&gt;(t));
      }
  
      std::vector&lt;std::unique_ptr&lt;X&gt;&gt; _classes;
  };
  </code></pre>
  
  <p>but I'm wondering if this is the way to go or if there is a more elegant way. Here I would have to always switch through the <code>enum</code>s to get the full type out of my Storage class, something like:</p>
  
  <pre><code>switch(_classes.front()-&gt;get_class_type()) {
  case class_type::type_A:
  {
      switch(_classes.front()-&gt;get_data_type()) {
      case data_type::type_int:
      {
           /* I finally know that it is A&lt;int&gt; */
      }
  /* ... */
  </code></pre>
  
  <p>Thanks in advance.</p>