<!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>P2308R0: 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">P2308R0: 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 />
February 10, 2023</p>
<h1 id="history">History</h1>
<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 called an <em>exemplar</em>. 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 exemplar 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 exemplar (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>
<p>Replace all uses <em>template-argument</em> in [temp.param]/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) <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>Insert before paragraph 2:</p>
<div class="ins">
<blockquote>
<p>When considering a template argument <em>A</em> for a non-type <em>template-parameter</em> of (possibly deduced) type <em>T</em>, a glvalue <em>exemplar</em> expression of type <em>T</em>, or of the referenced type if <em>T</em> is a reference type, is selected. The result of the examplar determines the value of the <em>template-parameter</em> and the identity of the specialization ([temp.type]).</p>
</blockquote>
</div>
<p>Change paragraph 2:</p>
<blockquote>
<p><s>A <em>template-argument</em> for a non-type <em>template-parameter</em></s><u>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 exemplar 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">
const <var>T</var> v = <var>A</var>;
</pre>
<p>is introduced. If the full-expression of the <em>init-declarator</em> for <code>v</code> is not a constant expression when interpreted as a <em>constant-expression</em> ([expr.const]), the program is ill-formed. The lifetime of <code>v</code> ends immediately after initializing it and any template parameter object (see below). The exemplar is <code>v</code>.</p>
</blockquote>
<blockquote>
<p>If <em>T</em> is a class type, the value of the exemplar determines the identity of the template parameter object for the parameter ([temp.param]). Each template parameter object <em>P</em> is copy-initialized from an unspecified exemplar whose value nominates <em>P</em>. If, for any such initialization:</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 produce a value not template-argument-equivalent ([temp.type]) to the value of the exemplar,</li>
</ol>
<p>the program is ill-formed.</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: template parameter contains pointer to temporary

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 temporary exemplar</u>
</pre>
</blockquote>
<h3 id="temp.type">#[temp.type]</h3>
<p>Change bullet (1.3):</p>
<blockquote>
<p><u>the exemplars ([temp.arg.nontype]) for </u>their corresponding non-type <em>template-argument</em>⁠s are template-argument-equivalent (see below)<s> after conversion to the type of the <em>template-parameter</em></s>, and</p>
</blockquote>
</body>
</html>
