<!DOCTYPE html>

<html><head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

     <style>

/**

 * SyntaxHighlighter

 * http://alexgorbatchev.com/SyntaxHighlighter

 *

 * SyntaxHighlighter is donationware. If you are using it, please donate.

 * http://alexgorbatchev.com/SyntaxHighlighter/donate.html

 *

 * @version

 * 3.0.83 (July 02 2010)

 * 

 * @copyright

 * Copyright (C) 2004-2010 Alex Gorbatchev.

 *

 * @license

 * Dual licensed under the MIT and GPL licenses.

 */

.syntaxhighlighter {

  background-color: white !important;

}

.syntaxhighlighter .line.alt1 {

  background-color: white !important;

}

.syntaxhighlighter .line.alt2 {

  background-color: white !important;

}

.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {

  background-color: #e0e0e0 !important;

}

.syntaxhighlighter .line.highlighted.number {

  color: black !important;

}

.syntaxhighlighter table caption {

  color: black !important;

}

.syntaxhighlighter .gutter {

  color: #afafaf !important;

}

.syntaxhighlighter .gutter .line {

  border-right: 3px solid #6ce26c !important;

}

.syntaxhighlighter .gutter .line.highlighted {

  background-color: #6ce26c !important;

  color: white !important;

}

.syntaxhighlighter.printing .line .content {

  border: none !important;

}

.syntaxhighlighter.collapsed {

  overflow: visible !important;

}

.syntaxhighlighter.collapsed .toolbar {

  color: blue !important;

  background: white !important;

  border: 1px solid #6ce26c !important;

}

.syntaxhighlighter.collapsed .toolbar a {

  color: blue !important;

}

.syntaxhighlighter.collapsed .toolbar a:hover {

  color: red !important;

}

.syntaxhighlighter .toolbar {

  color: white !important;

  background: #6ce26c !important;

  border: none !important;

}

.syntaxhighlighter .toolbar a {

  color: white !important;

}

.syntaxhighlighter .toolbar a:hover {

  color: black !important;

}

.syntaxhighlighter .plain, .syntaxhighlighter .plain a {

  color: black !important;

}

.syntaxhighlighter .comments, .syntaxhighlighter .comments a {

  color: #008200 !important;

}

.syntaxhighlighter .string, .syntaxhighlighter .string a {

  color: blue !important;

}

.syntaxhighlighter .keyword {

  color: #006699 !important;

}

.syntaxhighlighter .preprocessor {

  color: gray !important;

}

.syntaxhighlighter .variable {

  color: #aa7700 !important;

}

.syntaxhighlighter .value {

  color: #009900 !important;

}

.syntaxhighlighter .functions {

  color: #ff1493 !important;

}

.syntaxhighlighter .constants {

  color: #0066cc !important;

}

.syntaxhighlighter .script {

  font-weight: bold !important;

  color: #006699 !important;

  background-color: none !important;

}

.syntaxhighlighter .color1, .syntaxhighlighter .color1 a {

  color: gray !important;

}

.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {

  color: #ff1493 !important;

}

.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {

  color: red !important;

}



.syntaxhighlighter .keyword {

  font-weight: bold !important;

}

.syntaxhighlighter div.toolbar span a.toolbar_item{

   display: none !important;

} 

body .syntaxhighlighter .line {

    white-space: pre !important;

}

.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.clo,.opn,.pun{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.kwd,.tag,.typ{font-weight:700}.str{color:#060}.kwd{color:#006}.com{color:#600;font-style:italic}.typ{color:#404}.lit{color:#044}.clo,.opn,.pun{color:#440}.tag{color:#006}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}

    </style>



<title>Filling holes in Class Template Argument Deduction</title>

</head>



<body>

<p>P1021R5<br>

Mike Spertus, Symantec<br>

<a href="mailto:mike_spertus@symantec.com">mike_spertus@symantec.com</a><br>

Timur Doumler<br>

<a href="mailto:papers@timur.audio">papers@timur.audio</a><br>

Richard Smith<br>

<a href="mailto:richardsmith@google.com">richardsmith@google.com</a><br>

2019-08-05<br>

Audience: Core Working Group

</p>

<h1>Filling holes in Class Template Argument Deduction</h1>

This paper proposes filling several gaps in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html">Class Template Argument Deduction</a>.



<h2>Document revision history</h2>



<b>R0</b>, 2018-05-07: Initial version<br>

<b>R1</b>, 2018-10-07: Refocused paper on filling holes in CTAD<br>

<b>R2</b>, 2018-11-26: Following EWG guidance, removed proposal for CTAD from partial template argument lists<br>

<b>R3</b>, 2019-01-21: Added wording and change target to Core Working Group<br>

<b>R4</b>, 2019-06-17: Updated wording in response to CWG comments<br>

<b>R5</b>, 2019-08-05: Updated algorithm for aggregates; moved wording to separate wording papers.



<h2>Rationale</h2>

As one of us (Timur) has noted when giving public presentations on using

 class template argument deduction, there are a significant number of 

cases where it cannot be used. This always deflates the positive 

feelings from the rest of the talk because it is accurately regarded as 

artificially inconsistent. In particular, listeners are invariably 

surprised that it does not work with aggregate templates, type aliases, 

and inherited constructors.

    We will show in this paper

that these limitations can be safely removed. Note that some of these 

items were intentionally deferred from

    C++17 with the intent of adding them in C++20. 

<h2>Class Template Argument Deduction for aggregates</h2>

We propose that Class Template Argument Deduction works for aggregate initialization as one

	shouldn't have to choose between having aggregates and deduction. This is well illustrated

	by the following example:

<table border="1"><tbody><tr><th>C++17</th><th>Proposed</th></tr>

<tr><td><div><div id="highlighter_153831" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code><code class="cpp plain">&lt;</code><code class="cpp keyword bold">class</code> <code class="cpp plain">T&gt;</code></div><div class="line number2 index1 alt1"><code class="cpp keyword bold">struct</code> <code class="cpp plain">Point { T x; T y; };</code></div><div class="line number3 index2 alt2">&nbsp;</div><div class="line number4 index3 alt1"><code class="cpp comments">// Aggregate: Cannot deduce</code></div><div class="line number5 index4 alt2"><code class="cpp plain">Point&lt;</code><code class="cpp color1 bold">double</code><code class="cpp plain">&gt; p{3.0, 4.0};</code></div><div class="line number6 index5 alt1"><code class="cpp plain">Point&lt;</code><code class="cpp color1 bold">double</code><code class="cpp plain">&gt; p2{.x = 3.0, .y = 4.0};</code></div></div></td></tr></tbody></table></div></div></td>    

    <td><div><div id="highlighter_642490" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code><code class="cpp plain">&lt;</code><code class="cpp keyword bold">class</code> <code class="cpp plain">T&gt;</code></div><div class="line number2 index1 alt1"><code class="cpp keyword bold">struct</code> <code class="cpp plain">Point { T x; T y; };</code></div><div class="line number3 index2 alt2">&nbsp;</div><div class="line number4 index3 alt1"><code class="cpp comments">// Proposed: Aggregates deduce</code></div><div class="line number5 index4 alt2"><code class="cpp plain">Point p{3.0, 4.0};</code></div><div class="line number6 index5 alt1"><code class="cpp plain">Point p2{.x = 3.0, .y = 4.0};</code></div></div></td></tr></tbody></table></div></div></td>

    </tr></tbody></table>



For the code on the right hand side to work in C++17, the user would 

have to write an explicit deduction guide. We believe that this is 

unnecessary and error-prone boilerplate and that the necessary deduction

 guide should be implicitly synthesized by the compiler  from the 

arguments of a braced  or designated initializer during aggregate 

initialization.

<h3>Algorithm</h3>

<p>In the current Working Draft, an aggregate class is defined as a 

class with no user-declared or inherited constructors, no private or 

protected non-static data members, no virtual functions, and no virtual,

 private or protected base classes. While we would like to generate an 

aggregate deduction guide for class templates 

    that comply with these rules, we first need to consider the case 

where there is a dependent base

    class that may have virtual functions or virtual base classes, which would violate the rules

 for aggregates. Fortunately,

    that case does not cause a problem because any deduction guides that

 require one or more arguments

    will result in a compile-time error after instantiation, and 

non-aggregate classes without

    user-declared or inherited constructors generate a zero-argument 

deduction guide anyway.

    Based on the above, we can safely generate an aggregate deduction 

guide for class templates

    that comply with aggregate rules.    





</p><p>When <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0960r1.html">P0960R0</a>

 was discussed in Rapperswil, it was voted that in order to allow 

aggregate initialization from a parenthesized list of arguments, 

aggregate initialization should proceed as if there was a synthesized 

constructor. We can use a similar approach to also synthesize the

required additional deduction guide during class template argument

    deduction as follows:



</p><ol>

    <li>Given a primary class template <tt>C</tt>, determine whether it satisfies all the conditions for an aggregate class ([dcl.init.aggr]/1.1 - 1.4), except that we are not considering the possibility of dependent base classes violating those conditions.</li>

    <li>If yes, let <tt>x_1</tt>, ..., <tt>x_n</tt> be the elements of the initializer list.

    <li>Consider the elements ([dcl.init.aggr]/2) of the aggregate (which may or may not depend on its template arguments). For each initializer <tt>x_i</tt>, find the element <tt>e_i</tt> that this initializer would be initializing, according to the rules of aggregate initialization.</li>

    <li>Form a hypothetical constructor <tt>C(T_1, ..., T_N)</tt>, where <tt>T_i</tt> is declared type of the element  <tt>x_i</tt>.</li>

    <li>For the set of functions and function templates formed for 

[over.match.class.deduct], add an additional function template derived 

from this hypothetical constructor as described in 

[over.match.class.deduct]/1.</li>

</ol>



<h3>Brace elision</h3>

There is a slight complication resulting from subaggregates, and the 

fact that nested braces can be omitted when instantiating them:



<blockquote><div><div id="highlighter_734434" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">Foo { </code><code class="cpp color1 bold">int</code> <code class="cpp plain">x, y; };</code></div><div class="line number2 index1 alt1"><code class="cpp keyword bold">struct</code> <code class="cpp plain">Bar { Foo f; </code><code class="cpp color1 bold">int</code> <code class="cpp plain">z; };</code></div><div class="line number3 index2 alt2"><code class="cpp plain">Bar bar{1, 2};&nbsp;&nbsp; </code><code class="cpp comments">// Initializes bar.f.x and bar.f.y to 1; zero-initializes bar.z</code></div></div></td></tr></tbody></table></div></div></blockquote>



In this case, we have two initializers, but they do not map to the two elements of the aggregate type <tt>Bar</tt>, instead initializing the sub-elements of the first subaggregate element of type <tt>Foo</tt>. This in itself is not a problem, as we can still easily determine which element (or sub-element) is initialized by which initializer. However it becomes a bigger problem if one of the elements is dependent on a template parameter, and we cannot tell during CTAD whether it is a subaggregate or not (or how many sub-elements it holds:



</p><blockquote><div><div id="highlighter_611034" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">T&gt;</code></div><div class="line number2 index1 alt1"><code class="cpp keyword bold">struct</code> <code class="cpp plain">Bar { T f; </code><code class="cpp color1 bold">int</code> <code class="cpp plain">z; };&nbsp; </code><code class="cpp comments">// T might be a subaggregate!</code></div></div></td></tr></tbody></table></div></div></blockquote>



We therefore propose to avoid these problems by not considering brace elision for dependent types during class template argument deduction. Therefore, for example, <tt>Bar bar{1.0f, 2}</tt> deduces <tt>Bar&lt;float&gt;</tt>, which is exactly what the user would expect.



<h3>Deduction guide depends on initializer</h3>



Another interesting property of this algorithm is that the new deduction guide depends on the initializer, and might be different for each one. Therefore, even for the same class template, the set of deduction candidates is different depending on where in the code CTAD is performed. However, this is not novel. We already have several such situations in C++17: an explicit deduction guide can be declared later in the code, adding a new candidate to the set. As another example, it is possible to declare a primary template and then define it later. In this situation,  the set of deduction candidates will be different before and after that definition.



<h2>Class Template Argument Deduction for alias templates</h2>

While Class Template Argument Deduction makes type inferencing easier 

when constructing classes,

it doesn't work for type aliases, penalizing the use of type aliases and

 creating unnecessary inconsistency.We propose allowing Class Template 

Argument Deduction for type aliases as in the following example.



    <table border="1"><tbody><tr><th><tt>vector</tt></th><th><tt>pmr::vector</tt> (C++17)</th><th>pmr::vector (proposed)</th></tr>

<tr>

    <td>

<div><div id="highlighter_776658" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">vector v = {1, 2, 3};</code></div><div class="line number2 index1 alt1"><code class="cpp plain">vector v2(cont.begin(), cont.end());</code></div></div></td></tr></tbody></table></div></div>

    </td>

    <td><div><div id="highlighter_343467" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">pmr::vector&lt;</code><code class="cpp color1 bold">int</code><code class="cpp plain">&gt; v = {1, 2, 3};</code></div><div class="line number2 index1 alt1"><code class="cpp plain">pmr::vector&lt;decltype(cont)::value_type&gt; v2(cont.begin(), cont.end());</code></div></div></td></tr></tbody></table></div></div>

    </td>

<td><div><div id="highlighter_223547" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">pmr::vector v = {1, 2, 3};</code></div><div class="line number2 index1 alt1"><code class="cpp plain">pmr::vector v2(cont.begin(), cont.end());</code></div></div></td></tr></tbody></table></div></div>

</td>

</tr></tbody></table>

    <tt>pmr::vector</tt> also serves to illustrate another interesting case. While one might

    be tempted to write

    <blockquote><div><div id="highlighter_174382" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">pmr::vector pv({1, 2, 3}, mem_res); </code><code class="cpp comments">// Ill-formed (C++17 and proposed)</code></div></div></td></tr></tbody></table></div></div></blockquote>

    this example is ill-formed by the normal rules of template argument deduction because

    <tt>pmr::memory_resource</tt> fails to 

    deduce <tt>pmr::polymorphic_allocator&lt;int&gt;</tt> in the  second argument. 

    <p>While this is to be expected, one suspects that had class template argument deduction

        for alias templates been around when <tt>pmr::vector</tt> was being designed,

        the committee would have considered allowing such an inference as safe and useful in this context.

        If that was desired, it could easily have been achieved 

        by indicating that the <code>pmr::allocator</code> template parameter should be considered non-deducible:

    </p><blockquote><div><div id="highlighter_550973" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">namespace</code> <code class="cpp plain">pmr {</code></div><div class="line number2 index1 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">template</code><code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">T&gt;</code></div><div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">using</code> <code class="cpp plain">vector = std::vector&lt;T, type_identity_t&lt;pmr::polymorphic_allocator&lt;T&gt;&gt;&gt;; </code><code class="cpp comments">// See P0887R1 for type_identity_t</code></div><div class="line number4 index3 alt1"><code class="cpp plain">}</code></div><div class="line number5 index4 alt2"><code class="cpp plain">pmr::vector pv({1, 2, 3}, mem_res); </code><code class="cpp comments">// OK with this definition</code></div></div></td></tr></tbody></table></div></div></blockquote>

 Finally, in the spirit of alias templates being simply an alias for the type, we do not propose

allowing the programmer to write explicit deduction guides specifically for an alias

template.

<h3>Algorithm</h3>

For deriving deduction guides for the alias templates from guides in the class, we use the following approach (for which we are very grateful for the invaluable assistance of Richard Smith):

<ol><li>Deduce template parameters for the deduction guide by deducing the right hand side of

    the deduction guide from the alias template. We do not require that this deduces all the template

    parameters as nondeducible contexts may of course occur in general</li>

    <li>Substitute any deductions made back into the deduction guides. Since the previous step may not

    have deduced all template parameters of the deduction guide, the new guide may have template

    parameters from both the type alias and the original deduction guide.</li>

    <li>Derive the corresponding deduction guide for the alias template by 

    deducing the alias from the result type. Note that a constraint may be necessary

    as whether and how to deduce the alias from the result type may depend on the

    actual argument types.</li>

    <li>The guide generated from the copy deduction guide should be given

    the precedence associated with copy deduction guides during overload resolution</li></ol>

Let us illustrate this process with an example. Consider the following example:

<blockquote><div><div id="highlighter_41752" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code><code class="cpp plain">&lt;</code><code class="cpp keyword bold">class</code> <code class="cpp plain">T&gt; </code><code class="cpp keyword bold">using</code> <code class="cpp plain">P = pair&lt;</code><code class="cpp color1 bold">int</code><code class="cpp plain">, T&gt;;</code></div></div></td></tr></tbody></table></div></div></blockquote>

Naively using the deduction guides from pair is not ideal because they

    cannot necessarily deduce objects of type <tt>P</tt> even

    from arguments that should obviously work, like <tt>P({}, 0)</tt>. However,

    let us apply the above procedure. The relevant deduction guide is

<blockquote><div><div id="highlighter_368505" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code><code class="cpp plain">&lt;</code><code class="cpp keyword bold">class</code> <code class="cpp plain">A, </code><code class="cpp keyword bold">class</code> <code class="cpp plain">B&gt; pair(A, B) -&gt; pair&lt;A, B&gt;</code></div></div></td></tr></tbody></table></div></div></blockquote>

Deducing <code>(A, B)</code> from <code>(int, T)</code> yield <code>int</code> for <code>A</code>

    and <code>T</code> for <code>B</code>. Now substitute back into the deduction guide to get

    a new deduction guide

<blockquote><div><div id="highlighter_147664" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code><code class="cpp plain">&lt;</code><code class="cpp keyword bold">class</code> <code class="cpp plain">T&gt; pair(</code><code class="cpp color1 bold">int</code><code class="cpp plain">, T) -&gt; pair&lt;</code><code class="cpp color1 bold">int</code><code class="cpp plain">, T&gt;;</code></div></div></td></tr></tbody></table></div></div></blockquote>

Deducing the template arguments for the alias template from this gives us the following deduction guide for the alias template 

<blockquote><div><div id="highlighter_362756" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code><code class="cpp plain">&lt;</code><code class="cpp keyword bold">class</code> <code class="cpp plain">T&gt; P(</code><code class="cpp color1 bold">int</code><code class="cpp plain">, T) -&gt; P&lt;T&gt;;</code></div></div></td></tr></tbody></table></div></div></blockquote>

A repository of additional expository materials and worked out examples used in the refinement of this algorithm 

    is maintained <a href="https://htmlpreview.github.io/?https://github.com/mspertus/CTAD_POST_CPP17/master/CTAD_alias_examples.html">online</a>.

<h2>Deducing from inherited constructors</h2>

In C++17, deduction guides (implicit and explicit) are not inherited when constructors are inherited.

	According to the C++ Core Guidelines <a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-inheriting">C.52</a>,

 you should “use inheriting constructors to import constructors into a 

derived class that does not need further explicit initialization”. As 

the creator of such a thin wrapper has not asked in any way for the 

derived class to behave differently under construction, our experience 

is that users are

surprised that construction behavior changes:

<table border="1"><tbody><tr><td colspan="2">

<div><div id="highlighter_36110" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">T&gt; </code><code class="cpp keyword bold">struct</code> <code class="cpp plain">CallObserver requires Invocable&lt;T&gt; { </code></div><div class="line number2 index1 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">CallObserver(T &amp;&amp;) : t(std::forward&lt;T&gt;(t)) {}</code></div><div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">virtual</code> <code class="cpp keyword bold">void</code> <code class="cpp plain">observeCall() { t(); }</code></div><div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">T t;</code></div><div class="line number5 index4 alt2"><code class="cpp plain">};</code></div><div class="line number6 index5 alt1">&nbsp;</div><div class="line number7 index6 alt2"><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">typename</code> <code class="cpp plain">T&gt; </code><code class="cpp keyword bold">struct</code> <code class="cpp plain">CallLogger : </code><code class="cpp keyword bold">public</code> <code class="cpp plain">CallObserver&lt;T&gt; { </code></div><div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">using</code> <code class="cpp plain">CallObserver&lt;T&gt;::CallObserver; </code></div><div class="line number9 index8 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">virtual</code> <code class="cpp keyword bold">void</code> <code class="cpp plain">observeCall() override { cout &lt;&lt; </code><code class="cpp string">"calling"</code><code class="cpp plain">; t();&nbsp; }</code></div><div class="line number10 index9 alt1"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>

</td></tr>

<tr><th>C++17</th> <th>Proposed</th></tr>

<tr><td>

	<div><div id="highlighter_155720" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">CallObserver observer([]() { </code><code class="cpp comments">/* ... */</code> <code class="cpp plain">}); </code><code class="cpp comments">// OK</code></div><div class="line number2 index1 alt1"><code class="cpp plain">CallLogger&lt;</code><code class="cpp comments">/*????*/</code><code class="cpp plain">&gt; logger([]() { </code><code class="cpp comments">/* ... */</code> <code class="cpp plain">});</code></div></div></td></tr></tbody></table></div></div>

</td>

<td><div><div id="highlighter_787208" class="syntaxhighlighter nogutter  cpp"><div class="toolbar"><span><a href="#" class="toolbar_item command_help help">?</a></span></div><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="cpp plain">CallObserver observer([]() { </code><code class="cpp comments">/* ... */</code> <code class="cpp plain">}); </code><code class="cpp comments">// OK</code></div><div class="line number2 index1 alt1"><code class="cpp plain">CallLogger logger([]() { </code><code class="cpp comments">/* ... */</code> <code class="cpp plain">}); </code><code class="cpp comments">// Now OK</code></div></div></td></tr></tbody></table></div></div>

    </td></tr></tbody></table>

Note that inheriting the constructors of a base class must include 

inheriting all the deduction guides, not just the implicit ones. As a 

number of standard library

writers use explicit guides to behave “as-if” their classes were defined

 as in the standard, such internal implementation details

details would become visible if only the internal guides were inherited.

 We of course use the same algorithm

    for determining deduction guides for the base class template as 

described above for alias templates.

<h2>Wording</h2>



<p>The wording for CTAD for aggregates and CTAD for alias templates has been included into the C++20 committee draft and can be found in <a href="https://wg21.link/p1816r0">P1816R0</a> and <a href="https://wg21.link/p1814r0">P1814R0</a>, respectively.</p>



<p>The wording for CTAD from inherited constructors was not finalized in time for the C++20 committee draft, and will be published in a separate wording paper at a later point in time.</p>



    <script type="text/javascript">

	SyntaxHighlighter.defaults['gutter'] = false;

     SyntaxHighlighter.all()

</script>

	</body></html>