<html>
<style>
ins {background-color:#A0FFA0}
del {background-color:#FFA0A0}
strong { color: #2020ff }
#hidedel:checked ~ * del, #hidedel:checked ~ * del * { display:none; visibility:hidden }
</style>
<title>Drafting for class template argument deduction issues</title>
<body>
Jason Merrill
<br>2017-03-02
<br>P0620R0

<h1>Drafting for class template argument deduction issues</h1>

<h3>Discussion</h3>

This paper is intended to resolve
<ul>
  <li>The direction on wrapping vs. copying from EWG on Monday in Kona</li>
  <li>Handling of implicitly declared constructors (<a href="http://lists.isocpp.org/core/2016/09/0947.php">discussed here</a>)</li>
  <li>Access control (<a href="http://lists.isocpp.org/core/2017/02/1720.php">discussed here</a>)</li>
  <li>Redeclaration (<a href="http://lists.isocpp.org/core/2017/02/1695.php">discussed here</a>)</li>
  <li>Default-initialized declarations (<a href="http://lists.isocpp.org/core/2017/02/1822.php">discussed here</a>)</li>
  <li>Deduction in new-expressions</li>
  <li>Deduction in variable declarations other than simple-declarations</li>
</ul>

<h3>Proposed Resolution</h3>

<input type="checkbox" id="hidedel" />Hide deleted text

<p>Change 5.3.4&para;2:</p>
<blockquote>
  ...
  <p>If a placeholder type (7.1.7.4) appears in the type-specifier-seq of a
    new-type-id or type-id of a new-expression, the <del>new-expression shall
    contain a new-initializer of the form</del>
  <blockquote>
    <del>( assignment-expression )</del>
  </blockquote>
  <del>The</del>
  allocated type is deduced <del>from the new-initializer</del> as follows:
  Let <del>e be the assignment-expression in the new-initializer</del> <ins>I
  be the new-initializer, if any,</ins> and T be the new-type-id or type-id of
  the new-expression,
  then the
  allocated type is the type deduced for the
  variable x in the invented declaration (7.1.7.4):
  <blockquote>
    T x <del>(e)</del> <ins>I</ins> ;
  </blockquote>
  [ Example:
<blockquote>
  <pre>
new auto(1);  // allocated type is int
auto x = new auto(’a’);  // allocated type is char, x is of type char*

<ins>template&lt;class T> struct A { A(T,T); };</ins>
<ins>auto y = new A{1,2}; // allocated type is A&lt;int></ins>
</pre></blockquote>
&mdash; end example ]
</blockquote>

<p>Change 7.1.7.2&para;2:</p>
<blockquote>
  ... A type-specifier of the form typename<sub>opt</sub>
  nested-name-specifier<sub>opt</sub> template-name is a placeholder for a
  deduced class type<del> and shall appear only as a decl-specifier in the
  decl-specifier-seq of a simple-declaration (7.1.7.5) or as the
  simple-type-specifier in an explicit type conversion (functional notation)
  (5.2.3)</del>. The template-name shall name a class template that is not an
  injected-class-name. ...
</blockquote>

<p>Change 7.1.7.4&para;4-5:</p>
<blockquote>
  The type of a variable declared using auto or decltype(auto) is deduced from
  its initializer. This use is allowed <del>when declaring variables in a block
  (6.3), in namespace scope (3.3.6), and in an init-statement (Clause
  6)</del> <ins>in an initializing declaration (8.6) of a variable</ins>.
  auto or decltype(auto) shall appear as one of the decl-specifiers in the
  decl-specifier-seq and the decl-specifier-seq shall be followed by one or
  more <del>init-</del> declarators, each of which shall have a non-empty
  initializer. In an initializer of the form
<blockquote>
  ( expression-list )
</blockquote>
  the expression-list shall be a single assignment-expression. [ Example: ... &mdash;end example ]

<p>A placeholder type can also be used <del>in declaring a variable in the
    condition of a selection statement (6.4) or an iteration statement
    (6.5),</del> in the type-specifier-seq in the new-type-id or type-id of a
    new-expression (5.3.4)<del>, in a for-range-declaration, in declaring a
    static data member with a brace-or-equal-initializer that appears within
    the member-specification of a class definition (9.2.3.2),</del> and as a
    decl-specifier of the parameter-declaration’s decl-specifier-seq in a
    template-parameter (14.1).
</blockquote>

<p>Change 7.1.7.5:</p>
<blockquote>
  If a placeholder for a deduced class type appears as a decl-specifier in the
  decl-specifier-seq of <del>a simple-</del> <ins>an initializing</ins>
  declaration <ins>(8.6) of a variable</ins>, the <del>init-declarator of
  that declaration shall be of the form</del>
    <blockquote>
      <del>declarator-id attribute-specifier-seq opt initializer</del>
    </blockquote>
    <del>The</del> placeholder is replaced by the return type of the function
    selected by overload resolution for class template deduction (13.3.1.8). If
    the <ins>decl-specifier-seq is followed by an</ins> init-declarator-list
    <ins>or member-declarator-list containing</ins> <del>contains</del> more
    than one <del>init-</del> declarator, the type that replaces the
    placeholder shall be the same in each deduction.

<p><ins>A placeholder for a deduced class type can also be used in the
  type-specifier-seq in the new-type-id or type-id of a new-expression (5.3.4),
  or as the simple-type-specifier in an explicit type conversion (functional
  notation) (5.2.3).  A placeholder for a deduced class type shall not appear
  in any other context.</ins>

    [ Example:<blockquote><pre>
template&lt;class T> struct container {
  container(T t) {}
  template&lt;class Iter> container(Iter beg, Iter end);
};
template&lt;class Iter>
container(Iter b, Iter e) -> container&lt;typename std::iterator_traits&lt;Iter>::value_type>;
std::vector&lt;double> v = { /* ... */ };

container c(7);	// OK, deduces int for T
auto d = container(v.begin(), v.end()); // OK, deduces double for T
container e{5, 6}; // error, int is not an iterator
</pre></blockquote>&mdash; end example ]
</blockquote>

<p>Add to the end of 8.6:</p>

<blockquote>
  <ins>A declaration that specifies the initialization of a variable, whether
    from an explicit initializer or by default-initialization, is called
    the <i>initializing declaration</i> of that variable.  [ Note: In most cases this
    is the defining declaration (3.1) of the variable, but the initializing
    declaration of a non-inline static data member (9.2.3.2) might be the
    declaration within the class definition and not the definition at namespace
    scope. &mdash; end note ]</ins>
</blockquote>

<p>Change 13.3.1.8:</p>

<blockquote>
  A set of functions and function templates is formed comprising: <ul>
    <li>For each constructor of the <ins>primary</ins> class template
      designated by the template-name, <ins>if the template is defined,</ins> a
      function template with the following properties:</li><ul>
      <li>The template parameters are the template parameters of the class template followed by the
	template parameters (including default template arguments) of the constructor, if any.</li>
      <li>The types of the function parameters are those of the constructor.</li>
      <li>The return type is the class template specialization designated by the template-name and template
	arguments corresponding to the template parameters obtained from the class template.</li></ul>
    <li><ins>If the primary class template C is not defined or does not declare
	any constructors, an additional function template derived as above from
	a hypothetical constructor <code>C()</code>. </ins></li>
    <li><ins>An additional function template derived as above from a
	hypothetical constructor <code>C(C)</code>, called the <i>copy deduction candidate</i>. </ins></li>
    <li>For each deduction-guide, a function or function template with the following properties:</li><ul>
      <li>The template parameters, if any, and function parameters are those of the deduction-guide.</li>
      <li>The return type is the simple-template-id of the deduction-guide.</li>
  </ul></ul>

  Initialization and overload resolution are performed as described in 8.6 and
  13.3.1.3, 13.3.1.4, or 13.3.1.7 (as appropriate for the type of
  initialization performed) for an object of a hypothetical class type, where
  the selected functions and function templates are considered to be the
  constructors of that class type for the purpose of forming an overload set,
  and the initializer is provided by the context in which class template
  argument deduction was performed. Each such notional constructor is
  considered to be explicit if the function or function template was generated
  from a constructor or deduction-guide that was declared explicit.  <ins>All
  such notional constructors are considered to be public members of the
  hypothetical class type.</ins>
</blockquote>

<p>In 13.3.3&para;1, move the deduction guide bullet after partial ordering:</p>
<blockquote>
  <ul><li>...</li>
    <li><del>F1 is generated from a deduction-guide (13.3.1.8) and F2 is not [ Example:</del>
<pre>
  <del>template &lt;class T> struct A {</del>
    <del>A(T, int*);  // #1</del>
    <del>A(A&lt;T>&, int*); // #2</del>
    <del>enum { value };</del>
  <del>};</del>

  <del>template &lt;class T, int N = T::value> A(T&&, int*) -> A&lt;T>;  // #3</del>

  <del>A a{1, 0};  // uses #1 to deduce A&lt;int> and initializes with #1</del>
  <del>A b{a, 0};  // uses #3 (not #2) to deduce A&lt;A&lt;int>&> and initializes with #1</del>
</pre>
<del>&mdash; end example ] or, if not that,</del>
    </li>
    <li>F1 is not a function template specialization and F2 is a function template specialization, or, if not that,</li>
    <li>F1 and F2 are function template specializations, and the function template for F1 is more specialized
      than the template for F2 according to the partial ordering rules described in 14.5.6.2<ins>, or, if not that,</ins>
      <del>.</del>
    </li>
    <li><ins>F1 is generated from a deduction-guide (13.3.1.8) and F2 is
	not, or, if not that,</ins></li>
    <li><ins>F1 is the copy deduction candidate (13.3.1.8) and F2 is not, or,
    if not that,</ins></li>
    <li><ins>F1 is generated from a non-template constructor and F2 is
    generated from a constructor template. [ Example:</ins>
<blockquote><pre>
<ins>template &lt;class T> struct A {</ins>
  <ins>using value_type = T;</ins>
  <ins>A(value_type); // #1</ins>
  <ins>A(const A&); // #2</ins>
  <ins>A(T, T, int); // #3</ins>
  <ins>template&lt;class U> A(int, T, U); // #4</ins>
<ins>}; // A(A); #5, the copy deduction candidate</ins>

<ins>A x (1, 2, 3); // uses #3, generated from a non-template constructor</ins>

<ins>template &lt;class T> A(T) -> A&lt;T>;  // #6, less specialized than #5</ins>

<ins>A a (42); // uses #6 to deduce A&lt;int> and #1 to initialize</ins>
<ins>A b = a;  // uses #5 to deduce A&lt;int> and #2 to initialize</ins>

<ins>template &lt;class T> A(A&lt;T>) -> A&lt;A&lt;T>>;  // #7, as specialized as #5</ins>

<ins>A b2 = a;  // uses #7 to deduce A&lt;A&lt;int>> and #1 to initialize</ins>
</pre></blockquote>
      <ins>&mdash;end example ]</ins>
  </li>  </ul>
</blockquote>

Change 14.9:
<blockquote>
  The same restrictions apply to the parameter-declaration-clause of a
  deduction guide as in a function declaration (8.3.5). The simple-template-id
  shall name a class template specialization. The template-name shall be the
  same identifier as the template-name of the simple-template-id. A
  deduction-guide shall be declared in the same scope as the corresponding
  class template <ins>and, for a member class template, with the same
  access</ins>.  <ins>Two deduction guide declarations in the same translation
  unit for the same class template shall not have equivalent
    parameter-declaration-clauses.</ins>
</blockquote>
</body>
