title: variadic template function to concatenate std::vector containers
body: <p>While learning about template parameter packs, I'm trying to write a clever, simple function to efficiently append two or more <code>std::vector</code> containers together.</p>
  
  <p>Below are two initial solutions.</p>
  
  <p>Version 1 is elegant but buggy, as it relies on side-effects during the expansion of the parameter pack, and the order of evaluation is undefined.</p>
  
  <p>Version 2 works, but relies on a helper function that requires two cases.  Yuck.</p>
  
  <p>Can you see if you can come up with a simpler solution?
  (For efficiency, the vector data should not be copied more than once.)</p>
  
  <pre><code>#include &lt;vector&gt;
  #include &lt;iostream&gt;
  
  // Append all elements of v2 to the end of v1.
  template&lt;typename T&gt;
  void append_to_vector(std::vector&lt;T&gt;&amp; v1, const std::vector&lt;T&gt;&amp; v2) {
      for (auto&amp; e : v2) v1.push_back(e);
  }
  
  // Expand a template parameter pack for side effects.
  template&lt;typename... A&gt; void ignore_all(const A&amp;...) { }
  
  // Version 1: Concatenate two or more std::vector&lt;&gt; containers into one.
  // Nicely simple, but buggy as the order of evaluation is undefined.
  template&lt;typename T, typename... A&gt;
  std::vector&lt;T&gt; concat1(std::vector&lt;T&gt; v1, const A&amp;... vr) {
      // Function append_to_vector() returns void, so I enclose it in (..., 1).
      ignore_all((append_to_vector(v1, vr), 1)...);
      // In fact, the evaluation order is right-to-left in gcc and MSVC.
      return v1;
  }
  
  // Version 2:
  // It works but looks ugly.
  template&lt;typename T, typename... A&gt;
  void concat2_aux(std::vector&lt;T&gt;&amp; v1, const std::vector&lt;T&gt;&amp; v2) {
      append_to_vector(v1, v2);
  }
  
  template&lt;typename T, typename... A&gt;
  void concat2_aux(std::vector&lt;T&gt;&amp; v1, const std::vector&lt;T&gt;&amp; v2, const A&amp;... vr) {
      append_to_vector(v1, v2);
      concat2_aux(v1, vr...);
  }
  
  template&lt;typename T, typename... A&gt;
  std::vector&lt;T&gt; concat2(std::vector&lt;T&gt; v1, const A&amp;... vr) {
      concat2_aux(v1, vr...);
      return v1;
  }
  
  int main() {
      const std::vector&lt;int&gt; v1 { 1, 2, 3 };
      const std::vector&lt;int&gt; v2 { 4 };
      const std::vector&lt;int&gt; v3 { 5, 6 };
      for (int i : concat1(v1, v2, v3)) std::cerr &lt;&lt; " " &lt;&lt; i;
      std::cerr &lt;&lt; "\n";          // gcc output is:  1 2 3 5 6 4
      for (int i : concat2(v1, v2, v3)) std::cerr &lt;&lt; " " &lt;&lt; i;
      std::cerr &lt;&lt; "\n";          // gcc output is:  1 2 3 4 5 6
  }
  </code></pre>