title: Extending 2 arguments [x, y] into variable size parameter pack [x, ... x, y]
body: <p>I'm writing a custom multi layer perceptron (MLP) implementation in C++. All but the last layer share one activation function <code>foo</code>, with the final layer having a separate activation <code>bar</code>. I'm trying to write my code such that it's able to handle models of this type with a varying number of layers, like at <a href="https://godbolt.org/z/TTMYv8sss" rel="nofollow noreferrer">this Godbolt link, reproduced below</a>. Unfortunately, as written, I've had to hardcode the parameter pack for activation functions, and thus the code in the link only compiles for <code>N = 5</code>.</p>
  <p>Is there a way to create a custom parameter pack from the two activation functions which is able to &quot;left-extend&quot; the first argument, such that I can then compile the code above (after suitably updating the call to <code>computeIndexedLayers</code> in <code>computeMlp</code>? Specifically, I'm thinking of some utility which can yield parameter packs like:</p>
  <pre class="lang-cpp prettyprint-override"><code>template &lt;size_t N, typename ActivationMid, typename ActivationLast&gt;
  struct makeActivationSequence {}; // What goes here?
  
  makeActivationSequence&lt;0&gt;(foo, bar) -&gt; []
  makeActivationSequence&lt;1&gt;(foo, bar) -&gt; [bar]
  makeActivationSequence&lt;2&gt;(foo, bar) -&gt; [foo, bar]
  makeActivationSequence&lt;3&gt;(foo, bar) -&gt; [foo, foo, bar]
  makeActivationSequence&lt;4&gt;(foo, bar) -&gt; [foo, foo, foo, bar]
  ...
  </code></pre>
  <p>Looking at the <a href="https://stackoverflow.com/questions/49669958/details-of-stdmake-index-sequence-and-stdindex-sequence">details of std::index_sequence</a> I believe something similar might work here, but it's unclear to me how I'd modify that approach to work with the two different types.</p>
  <p>Please note also that I'm specifically limited to C++14 here due to some toolchain issues, so solutions that take advantage of e.g. <code>if constexpr</code> (as in the linked std::index_sequence details) won't work.</p>
  <p>Code from the above Godbolt link, reproduced below for completeness:</p>
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;cstddef&gt;
  #include &lt;utility&gt;
  #include &lt;cstdio&gt;
  
  template &lt;size_t LayerIndex, typename Activation&gt;
   void computeIndexedLayer(
      const Activation&amp; activation) {
          printf(&quot;Doing work for layer %zu, activated output %zu\n&quot;, LayerIndex, activation(LayerIndex));
      }
  
  template &lt;
      std::size_t... index,
      typename... Activation&gt;
      void computeIndexedLayers(
      std::index_sequence&lt;index...&gt;, // has to come before Activation..., otherwise it'll get eaten
      Activation&amp;&amp;... activation) {
    (void)std::initializer_list&lt;int&gt;{
        (computeIndexedLayer&lt;index + 1&gt;(
             std::forward&lt;Activation&gt;(activation)),
         0)...};
  }
  
  template &lt;size_t N, typename ActivationMid, typename ActivationLast&gt;
  void computeMlp(ActivationMid&amp;&amp; mid, ActivationLast&amp;&amp; last) {
    computeIndexedLayers(std::make_index_sequence&lt;N&gt;(),
      std::forward&lt;ActivationMid&gt;(mid),
      std::forward&lt;ActivationMid&gt;(mid),
      std::forward&lt;ActivationMid&gt;(mid),
      std::forward&lt;ActivationMid&gt;(mid),
      std::forward&lt;ActivationLast&gt;(last)
      );
  }
  
  int main() {
      computeMlp&lt;5&gt;([](const auto&amp; x){ return x + 1;}, [](const auto&amp; x){ return x * 1000;});
  
      // Doesn't compile with any other choice of N due to mismatched pack lengths
      // computeMlp&lt;4&gt;([](const auto&amp; x){ return x + 1;}, [](const auto&amp; x){ return x * 1000;});
  }
  </code></pre>