title: Why can a char array be used in a constexpr function template but not in a static_assert
body: <p>I have a <code>constexpr</code> function template which takes a <code>char</code> array, the bounds of which are known at compile time:</p>
  
  <pre><code>template&lt;size_t N&gt;
  constexpr bool check(const char (&amp;arr)[N], size_t n = 0)
  </code></pre>
  
  <p>I can use this function with a string literal in a <code>static_assert</code> call.</p>
  
  <p>In this function I can walk through the string literal and perform calculations at compile time on the individual characters which make up the string.</p>
  
  <p>However, if I have another <code>constexpr</code> function template which also takes a char array / string literal</p>
  
  <pre><code>template&lt;size_t N&gt;
  constexpr void test(const char (&amp;arr)[N])
  </code></pre>
  
  <p>and from within that function I call <code>static_assert</code>, <code>arr</code> is no longer a constant expression, and so the <code>static_assert</code> is not allowed.</p>
  
  <p>Given the string literal's bounds are known at compile time, and it is therefore a statically sized array, and <code>size_t N</code> is a template parameter, I would have thought it should be possible to use <code>arr</code> in function <code>test</code>.</p>
  
  <p>It is not possible to call <code>test</code> with a non-constant array, so I would expect the compiler to know that <code>arr</code> is constant in <code>test</code>.</p>
  
  <p>Attempting to call <code>test</code> with a non-constant array results in a different (expected) error:</p>
  
  <pre><code>main.cpp:16:16: note:   template argument deduction/substitution failed:
  main.cpp:32:15: note:   mismatched types ‘const char [N]’ and ‘const char*’
  </code></pre>
  
  <h2>Question:</h2>
  
  <p><strong>Why can I use <code>const char (&amp;arr)[N]</code> <em>inside</em> a <code>static_assert</code>, but not pass it <em>to</em> a <code>static_assert</code>?</strong></p>
  
  <h2>Full example:</h2>
  
  <pre><code>#include &lt;cstddef&gt;
  #include &lt;stdexcept&gt;
  
  template&lt;size_t N&gt;
  constexpr bool check(const char (&amp;arr)[N], size_t n = 0)
  {
      return
          n &gt;= N ?
              true
          : arr[n] != '*' ?
              check(arr, n + 1)
          : throw std::logic_error("arr can't contain a '*'");
  }
  
  template&lt;size_t N&gt;
  constexpr void test(const char (&amp;arr)[N])
  {
      static_assert(check&lt;N&gt;(arr), ""); // non-constant condition for static assertion
  }
  
  int main()
  {
      static_assert(check("foo"), "");
  
      // fails to compile: string contains '*'
      //static_assert(check("foo*"), ""); 
  
      // fails to compile: ‘arr’ is not a constant expression
      //test("foo"); 
  
      return 0;
  }
  </code></pre>