title: why a constexpr expression of literal class type with a pointer subobject can't be a non-type template argument
body: <p>After looking at <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1837r0.html" rel="nofollow noreferrer">the</a> post about non-type template argument,I have a confusion for an example in that post,I cite the example here:  </p>
  
  <pre class="lang-cpp prettyprint-override"><code>struct VariableLengthString {
     const char *data_ = nullptr;
     constexpr VariableLengthString(const char *p) : data_(p) {}
     auto operator&lt;=&gt;(const VariableLengthString&amp;) const = default;
  };
  
  template&lt;VariableLengthString S&gt;
  int bar() {
     static int i = 0;
     return ++i;
  }
  
  int main() {
     int x = bar&lt;"hello"&gt;(); // ERROR
  }
  </code></pre>
  
  <p>The post says "the relevant wording is [temp.arg.nontype]/2",So I took a look at that rule,It constrains what can be a non-type template argument.  </p>
  
  <blockquote>
    <p>A template-argument for a non-type template-parameter shall be <strong>a converted constant expression</strong> of the type of the template-parameter.  </p>
  </blockquote>
  
  <p>So,I took a look at <code>converted constant expression</code>,Its definitions are here:  </p>
  
  <blockquote>
    <p>A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is <strong>a constant expression</strong> and the implicit conversion sequence contains only...  </p>
  </blockquote>
  
  <p>What is a constant expression?These rules are here:   </p>
  
  <blockquote>
    <p>An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:</p>
    
    <blockquote>
      <p>(2.2)  an invocation of a function other than <strong>a constexpr constructor for a literal class</strong>, a constexpr function, or an implicit invocation of a trivial destructor.  </p>
    </blockquote>
  </blockquote>
  
  <p>So,Is the class type <code>VariableLengthString</code> a literal class?Yes,it is.what rules can prove that are here:  </p>
  
  <blockquote>
    <p>A type is a literal type if it is:<br>
    1. possibly cv-qualified void; or<br>
    2. a scalar type; or<br>
    3. a reference type; or<br>
    4. an array of literal type; or<br>
    a possibly cv-qualified class type that has all of the following properties:  </p>
    
    <blockquote>
      <ol>
      <li>it has a trivial destructor,  </li>
      <li>it is either a closure type, an aggregate type, or has at least one constexpr constructor or constructor template (possibly inherited from a base class) that is not a copy or move constructor,    </li>
      <li>if it is not a union, all of its non-static data members and base classes are of non-volatile literal types.    </li>
      </ol>
    </blockquote>
  </blockquote>
  
  <p>The key point is that,Are these types of sub-objects of ojbects of type <code>VariableLengthString</code> all literal types? Does the class <code>VariableLengthString</code> have at least one constexpr constructor?Yes they are.Because of these rules:    </p>
  
  <blockquote>
    <p>Arithmetic types, enumeration types, <strong>pointer types</strong>, pointer to member types ([basic.compound]), std​::​nullptr_­t, and cv-qualified versions of these types are collectively called <strong>scalar types</strong>.  </p>
  </blockquote>
  
  <p>So,the sub-object <code>data_</code>,it's of type pointer.hence,it's scalar type,also a literal type.The bullet 3 is satisfied.Does <code>constexpr VariableLengthString(const char *p)</code> a constexpr constructor?Yes,it is,Because of these rules:   </p>
  
  <blockquote>
    <p>The definition of a constexpr constructor shall satisfy the following requirements:</p>
    
    <blockquote>
      <ol>
      <li>the class shall not have any virtual base classes;</li>
      <li>each of the parameter types shall be a literal type;</li>
      <li>every non-variant non-static data member and base class subobject shall be initialized  </li>
      </ol>
    </blockquote>
  </blockquote>
  
  <p>For <code>constexpr VariableLengthString(const char *p)</code>,these three rules are all be satisfied.In summary,the class <code>VariableLengthString</code> is a literal type and a constexpr expression of type <code>VariableLengthString</code> could be used as a non-type template argument,because it satisfies the requirement of being <strong>a converted constant expression</strong>.why the code above is ill-formed?If I miss something,please help me find out them.</p>