title: Push Back an Element to a Vector of Std::variant
body: <p>I'm having problems creating a <code>push_back</code> function for an <code>std::vector</code> of <code>std::variants</code>. This is a minimal implementation of my struct so far:</p>
  <pre><code>template&lt;class T, class Ts...&gt; //Must construct with at least 1 argument
  struct entity_container
  {
    entity_container(T arg1, Ts ...args) //constructor, populate vector of std::variant's
    {
      entities.push_back(std::forward&lt;decltype(arg1)&gt;(arg1));
  
      auto loop = [&amp;](auto&amp;&amp; arg)
      {
        entities.push_back(std::forward&lt;decltype(arg)&gt;(arg));
      }
      (loop(args),...);
    }
    
    std::vector&lt;std::variant&lt;T, Ts...&gt;&gt; entities;
  }
  </code></pre>
  <p>Now suppose I want to add a <code>push_back</code> function then there are some things I considered:</p>
  <ul>
  <li><p>if we are adding a type which already exists in the <code>std::variant</code> of <code>entity_container::entities</code> then we can simply use: <code>entities.push_back(entity)</code></p>
  </li>
  <li><p>if we are adding a <em>new</em> type to <code>entity_container::entities</code> then we need to extended the type of the <code>std::variant</code>, then create a new <code>std::vector</code> of said type and move all the elements from the old vector to the new one.</p>
  </li>
  </ul>
  <p>for this second case, I came across two posts:</p>
  <p><a href="https://stackoverflow.com/questions/52393831/can-i-extend-variant-in-c">extending a variant type in c++</a> and
  <a href="https://stackoverflow.com/questions/56246573/how-to-copy-an-element-of-stdvariant-to-a-variable-of-another-variant-type">copy/move elements between two std::variants</a></p>
  <p>So using these tools this is what I <em>wanted</em> to do for my <code>push_back</code> implementation:</p>
  <pre><code>template&lt;typename E&gt;
  void push_back(E&amp;&amp; entity)
  {
    if( /* E is a new type to the variant */)
    {
      //std::variant&lt;Old..., New&gt;  =  std::variant&lt;Old...&gt; + New
      using extended_type = t_variant_cat_t&lt;std::remove_reference_t&lt;decltype(Entities[0])&gt;, 
                                            std::remove_reference_t&lt;E&gt;&gt;;
  
      //construct (with the new element) a new entity_container with the extended type, 
      entity_container&lt;extended_type&gt; entities_new(entity);
  
      //move the entities from the old container to the new one
      for(auto&amp; ent : Entities)
        entities_new.entities.push_back(std::move(ent));    //all entities are moveable types
  
      //update replace the old container with the new
      entities = entities_new;
    }
    else /* E is not a new type to the variant */
    {
      entities.push_back(entity);
    }
  }
  </code></pre>
  <p>But there are many, <em>many</em> problems with this.</p>
  <ol>
  <li><p>How can we check that the type <code>E</code> is a new type to the variant?</p>
  </li>
  <li><p><code>extended_type</code> would be something along the lines of <code>std::variant&lt;T1, T2, T3, T4&gt;</code> but in reality we have to construct an <code>entity_container</code> as <code>entity_container&lt;T1, T2, T3, T4&gt;</code> - how can we convert from an <code>std::variant</code> to a type pack?</p>
  </li>
  <li><p>when we do <code>entities = entities_new</code> at the end, these two objects have different types and therefore cannot be assigned to one another (and that's even if (2) could be fixed)</p>
  </li>
  <li><p>Finally, we have to reconstruct the container <em>every single time</em> an element is pushed back. That's gonna be really slow.</p>
  </li>
  </ol>
  <p><strong>So my overall question is, does anyone have any ideas to fix the above problems, or perhaps a whole new approach to writing this function.</strong></p>
  <p>Side Note, the structure is used as so:</p>
  <pre><code>template&lt;class T&gt;
  struct Entity{};
  
  Entity&lt;A&gt; entity_a;
  Entity&lt;B&gt; entity_b;
  Entity&lt;C&gt; entity_c;
  
  entity_container c(entity_a, entity_b);
  
  c.push_back(entity_c);
  </code></pre>