title: constexpr to concatenate two or more char strings
body: <p>I'm trying to make a constexpr function that will concatenate an arbitrary number of char arrays by working from the following answer by Xeo, which concatenates two char arrays.</p>
  
  <p><a href="https://stackoverflow.com/a/13294458/1128289">https://stackoverflow.com/a/13294458/1128289</a></p>
  
  <pre><code>#include &lt;array&gt;
  
  template&lt;unsigned... Is&gt; struct seq{};
  template&lt;unsigned N, unsigned... Is&gt;
  struct gen_seq : gen_seq&lt;N-1, N-1, Is...&gt;{};
  template&lt;unsigned... Is&gt;
  struct gen_seq&lt;0, Is...&gt; : seq&lt;Is...&gt;{};
  
  template&lt;unsigned N1, unsigned... I1, unsigned N2, unsigned... I2&gt;
  constexpr std::array&lt;char const, N1+N2-1&gt; concat(char const (&amp;a1)[N1], char const (&amp;a2)[N2], seq&lt;I1...&gt;, seq&lt;I2...&gt;){
    return {{ a1[I1]..., a2[I2]... }};
  }
  
  template&lt;unsigned N1, unsigned N2&gt;
  constexpr std::array&lt;char const, N1+N2-1&gt; concat(char const (&amp;a1)[N1], char const (&amp;a2)[N2]){
    return concat(a1, a2, gen_seq&lt;N1-1&gt;{}, gen_seq&lt;N2&gt;{});
  }
  </code></pre>
  
  <p>My attempt thus far:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;array&gt;
  
  template&lt;unsigned... Is&gt; struct seq{};
  template&lt;unsigned N, unsigned... Is&gt;
  struct gen_seq : gen_seq&lt;N-1, N-1, Is...&gt;{};
  template&lt;unsigned... Is&gt;
  struct gen_seq&lt;0, Is...&gt; : seq&lt;Is...&gt;{};
  
  template&lt;unsigned N1, unsigned... I1, unsigned N2, unsigned... I2&gt;
  constexpr const std::array&lt;char, N1+N2-1&gt;
  concat_impl(
      const char (&amp;a1)[N1], const char (&amp;a2)[N2], seq&lt;I1...&gt;, seq&lt;I2...&gt;)
  {
      return {{ a1[I1]..., a2[I2]... }};
  }
  
  template&lt;unsigned N1, unsigned N2&gt;
  constexpr const std::array&lt;char, N1+N2-1&gt;
  concat(const char (&amp;a1)[N1], const char (&amp;a2)[N2])
  {
      return concat_impl(a1, a2, gen_seq&lt;N1-1&gt;{}, gen_seq&lt;N2&gt;{});
  }
  
  template&lt;unsigned N1, unsigned N2, class... Us&gt;
  constexpr auto
  concat(const char(&amp;a1)[N1], const char(&amp;a2)[N2], const Us&amp;... xs)
  -&gt; std::array&lt;char, N1 + decltype(concat(a2, xs...))::size() - 1&gt;
  {
      return concat(a1, concat(a2, xs...));
  }
  
  int main()
  {
      auto const s = concat("hi ", "there!");
      std::cout &lt;&lt; s.data() &lt;&lt; std::endl;
      // compile error:
      auto const t = concat("hi ", "there ", "how ", "are ", "you?");
      std::cout &lt;&lt; t.data() &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>Both gcc 4.9 and clang 3.5 give errors indicating that no function matching the <code>concat</code> inside the <code>decltype</code> expression can be found.</p>
  
  <p>clang:</p>
  
  <pre><code>error: no matching function for call to 'concat'
      auto const t = concat("hi ", "there ", "how ", "are ", "you?");
                     ^~~~~~
  ctconcat.cpp:105:16: note: candidate template ignored: substitution failure [with N1 = 4, N2 = 7, Us = &lt;char [5], char [5], char [5]&gt;]: no matching function for call to 'concat'
  constexpr auto concat(const char(&amp;a1)[N1], const char(&amp;a2)[N2], const Us&amp;... xs) -&gt; std::array&lt;char, N1 + decltype(concat(a2, xs...))::size() - 1&gt;
                 ^                                                                                                   ~~~~~~
  ctconcat.cpp:62:43: note: candidate function template not viable: requires 2 arguments, but 5 were provided
  constexpr const std::array&lt;char, N1+N2-1&gt; concat(const char (&amp;a1)[N1], const char (&amp;a2)[N2])
                                            ^
  1 error generated.
  </code></pre>
  
  <p>The errors from gcc and clang both indicate that the second <code>concat</code> function template is not a candidate for the <code>concat</code> in the <code>decltype</code> expression. Only the first template is considered. Why is that and how do I fix this?</p>
  
  <p><strong>Edit:</strong> Relevant question on why <code>decltype</code> can't be used recursively</p>
  
  <p><a href="https://stackoverflow.com/questions/3744400/trailing-return-type-using-decltype-with-a-variadic-template-function">trailing return type using decltype with a variadic template function</a></p>