<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>P2308R1: Template parameter initialization</title>
  <style type="text/css">
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
  <style type="text/css">
  div.del, section.del { background: #fcd; }
  div.ins, section.ins { background: #bfa; }
  .mv { background: #ddf; }
  s, .del { background: #ff8888; margin-right: 0.15ch; }
  u, .ins { background: #88ff88; }
  /* from https://stackoverflow.com/a/32456613 */
  div > blockquote, body > blockquote {
      display: list-item;
      list-style-type: "- ";
  }
  /* With a 3 em gutter and two columns, ANSI letter is 127 characters wide. */
  pre {
  		margin-left: 1.2em;
  }
  .tony {
    border-collapse: collapse;
  }
  .tony > tbody > tr {
    vertical-align: top;
  }
  tr.hr, tr.hr {
    border-bottom: thin solid #60a0b0;  /* relies on collapse */
  }
  </style>
</head>
<body>
<header>
<h1 class="title">P2308R1: Template parameter initialization<!-- -*- c++-md -*- --></h1>
</header>
<p><em>Audience</em>: CWG<br />
S. Davis Herring &lt;<a href="mailto:herring@lanl.gov">herring@lanl.gov</a>&gt;<br />
Los Alamos National Laboratory<br />
November 8, 2023</p>
<h1 id="history">History</h1>
<p>Since <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2308r0.html">r0</a>:</p>
<ul>
<li>Copyedited</li>
<li>Made the temporary class-type variable <code>constexpr</code></li>
<li>Clarified constraints on and selection of the template parameter object, removing the term “exemplar”</li>
</ul>
<p>R0: issue drafting converted to a paper after initial review.</p>
<h1 id="introduction">Introduction</h1>
<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2459">CWG2459</a> points out that there is no specification for how template parameters are initialized beyond “conversion to the type of the template-parameter” ([temp.type]/1.3) and “a converted constant expression ([expr.const]) of the type of the <em>template-parameter</em>” ([temp.arg.nontype]/2). As originally reported by Richard Smith, with template parameters of class type that have lvalue template parameter <em>objects</em> whose addresses can be examined during <a href="https://lists.isocpp.org/core/2019/11/7682.php">non-trivial construction</a> and for which <a href="https://lists.isocpp.org/core/2020/09/9868.php">“converted constant expression” is inadequate</a>, this becomes an acute concern. This paper resolves that issue, along with <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2450">CWG2450</a> (including an extension of <a href="https://wiki.edg.com/pub/Wg21summer2020/CoreWorkingGroup/cwg-2450.html">Jens Maurer’s drafting</a>) and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2049">CWG2049</a> which extend the set of potential initializers.</p>
<h1 id="approach">Approach</h1>
<p>To avoid address-based paradoxes, template arguments for a template parameter of class type <code>C</code> are used to first initialize a temporary of that type. No restrictions are imposed on the conversion from a template argument to a constructor parameter, since <code>explicit</code> and list-initialization may already be used to limit conversions in a similar fashion. Each temporary is used to copy-initialize the template parameter object to which it is (to be) template-argument-equivalent; the initialization is required to produce a template-argument-equivalent value. The multiple initializations of the template parameter object are (required to be) all equivalent and produce no side effects, so it is unobservable which happen. Using the same copy constructor for the temporary (when the template argument is a template parameter object) and for initializing the template parameter object guarantees that the same value will be selected, as required for deduction, specialization, and the notion of the current specialization to make sense.</p>
<h1 id="wording">Wording</h1>
<p>Relative to N4928.</p>
<h2 id="dcl.dcl">#[dcl.dcl]</h2>
<h3 id="dcl.fct.default">#[dcl.fct.default]</h3>
<p>Change paragraph 3:</p>
<blockquote>
<p>A default argument shall be specified only in the <em>parameter-declaration-clause</em> of a function declaration or <em>lambda-declarator</em> or in a <em>template-parameter</em> ([temp.param])<s>; in the latter case, the <em>initializer-clause</em> shall be an <em>assignment-expression</em></s>. […]</p>
</blockquote>
<h3 id="dcl.init.list">#[dcl.init.list]</h3>
<p>Insert before bullet (1.6):</p>
<div class="ins">
<blockquote>
<p>as a template argument ([temp.arg.nontype])</p>
</blockquote>
</div>
<h2 id="temp">#[temp]</h2>
<h3 id="temp.param">#[temp.param]</h3>
<p>Change paragraph 8:</p>
<blockquote>
<p>An <em>id-expression</em> naming a non-type <em>template-parameter</em> of class type <code>T</code> denotes a static storage duration object of type <code>const T</code>, known as a <em>template parameter object</em>, <s>whose value</s><u>which</u> is <s>that of</s><u>template-argument-equivalent ([temp.type]) to</u> the corresponding template argument after it has been converted to the type of the <em>template-parameter</em><u> ([temp.arg.nontype])</u>. <u>No two template parameter objects are template-argument-equivalent.</u> <s>All such template parameters in the program of the same type with the same value denote the same template parameter object. A template parameter object shall have constant destruction ([expr.const]).</s></p>
<p>[…]</p>
</blockquote>
<p>Replace all appearances of “<em>template-argument</em>” in paragraphs 12–16 with “template argument”.</p>
<h3 id="temp.names">#[temp.names]</h3>
<p>Change the grammar in paragraph 1:</p>
<blockquote>
<p>[…]</p>
<p><em>template-argument</em>:</p>
<blockquote>
<p><em>constant-expression</em><br />
<em>type-id</em><br />
<em>id-expression</em><br />
<u><em>braced-init-list</em></u></p>
</blockquote>
</blockquote>
<h3 id="temp.arg">#[temp.arg]</h3>
<h4 id="temp.arg.general">#[temp.arg.general]</h4>
<p>Change paragraph 4:</p>
<blockquote>
<p>[…]</p>
<p>For a <s><em>template-argument</em></s><u>template argument</u> that is a class type or a class template, the template definition has no special access rights to the members of the <s><em>template-argument</em></s><u>template argument</u>.</p>
<p>[<em>Example</em>:</p>
<p>[…]</p>
<p>— <em>end example</em>]</p>
</blockquote>
<p>Change paragraph 5:</p>
<blockquote>
<p>When template argument packs or default <s><em>template-argument</em></s><u>template argument</u>s are used, a <em>template-argument</em> list can be empty. […]</p>
</blockquote>
<p>Change paragraph 7:</p>
<blockquote>
<p>If the use of a <s><em>template-argument</em></s><u>template argument</u> gives rise to an ill-formed construct in the instantiation of a template specialization, the program is ill-formed.</p>
</blockquote>
<h4 id="temp.arg.nontype">#[temp.arg.nontype]</h4>
<p>Change paragraph 1:</p>
<blockquote>
If the type <code>T</code> of a <em>template-parameter</em> ([temp.param]) contains a placeholder type ([dcl.spec.auto]) or a placeholder for a deduced class type ([dcl.type.class.deduct]), the type of the parameter is the type deduced for the variable <code>x</code> in the invented declaration
<pre class="cpp">
T x = <var><s>template-argument</s><u>E</u></var> ;
</pre>
<p><u>where <em>E</em> is the template argument provided for the parameter.</u></p>
<p><u>[<em>Note</em>: <em>E</em> is a <em>template-argument</em> or (for a default template argument) an <em>initializer-clause</em>. — <em>end note</em>]</u></p>
<p>If a deduced parameter type is not permitted for a <em>template-parameter</em> declaration ([temp.param]), the program is ill-formed.</p>
</blockquote>
<p>Change paragraph 2:</p>
<blockquote>
<p><s>A <em>template-argument</em> for</s><u>The value of</u> a non-type <em>template-parameter</em><u> <em>P</em> of (possibly deduced) type <em>T</em> is determined from its template argument <em>A</em> as follows. If <em>T</em> is not a class type and <em>A</em> is not a <em>braced-init-list</em>, <em>A</em></u> shall be a converted constant expression ([expr.const]) of <s>the </s>type <s>of the <em>template-parameter</em></s><u><em>T</em>; the value of <em>P</em> is <em>A</em> (as converted)</u>.</p>
<p><s>[<em>Note</em>: If the <em>template-argument</em> is an overload set (or the address of such, including forming a pointer-to-member), the matching function is selected from the set ([over.over]). — <em>end note</em>]</s></p>
</blockquote>
<p>Insert before paragraph 3:</p>
<div class="ins">
<blockquote>
Otherwise, a temporary variable
<pre class="cpp">
constexpr <var>T</var> v = <var>A</var>;
</pre>
<p>is introduced. The lifetime of <code>v</code> ends immediately after initializing it and any template parameter object (see below). For each such variable, the <em>id-expression</em> <code>v</code> is termed a <em>candidate initializer</em>.</p>
</blockquote>
<blockquote>
<p>If <em>T</em> is a class type, a template parameter object ([temp.param]) exists that is constructed so as to be template-argument-equivalent to <code>v</code>; <em>P</em> denotes that template parameter object. <em>P</em> is copy-initialized from an unspecified candidate initializer that is template-argument-equivalent to <code>v</code>. If, for the initialization from any candidate initializer,</p>
<ol type="1">
<li>the initialization would be ill-formed, or</li>
<li>the full-expression of an invented <em>init-declarator</em> for the initialization would not be a constant expression when interpreted as a <em>constant-expression</em> ([expr.const]), or</li>
<li>the initialization would cause <em>P</em> to not be template-argument-equivalent ([temp.type]) to <code>v</code>,</li>
</ol>
<p>the program is ill-formed.</p>
</blockquote>
<blockquote>
<p>Otherwise, the value of <em>P</em> is that of <code>v</code>.</p>
</blockquote>
</div>
<p>Change the example in paragraph 4:</p>
<blockquote>
<p>[…]</p>
<pre class="cpp">
template&lt;auto n&gt; struct B { /* ... */ };
B&lt;5&gt; b1;                        // OK, template parameter type is int
B&lt;'a'&gt; b2;                      // OK, template parameter type is char
B&lt;2.5&gt; b3;                      // OK, template parameter type is double
B&lt;void(0)&gt; b4;                  // error: template parameter type cannot be void
<u>
template&lt;int i&gt; struct C { /* ... */ };
C&lt;{ 42 }&gt; c1;  // OK

struct J1 {
&nbsp;&nbsp;J1 *self=this;
};
B&lt;J1{}&gt; j1;  // error: initialization of template parameter object
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// is not a constant expression

struct J2 {
&nbsp;&nbsp;J2 *self=this;
&nbsp;&nbsp;constexpr J2() {}
&nbsp;&nbsp;constexpr J2(const J2&) {}
};
B&lt;J2{}&gt; j2;  // error: template parameter object not
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// template-argument-equivalent to introduced temporary</u>
</pre>
</blockquote>
<h3 id="temp.type">#[temp.type]</h3>
<p>Change bullet (1.3):</p>
<blockquote>
<p><u>the template parameter values determined by </u>their corresponding non-type <s><em>template-argument</em>⁠s</s><u>template arguments ([temp.arg.nontype])</u> are template-argument-equivalent (see below)<s> after conversion to the type of the <em>template-parameter</em></s>, and</p>
</blockquote>
</body>
</html>
