<html>

<head>
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
<meta name=Generator content="Microsoft Word 15 (filtered)">
<style>
<!--
 /* Font Definitions */
 @font-face
	{font-family:"Cambria Math";
	panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
	{font-family:LMRoman10-Bold;
	panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
	{font-family:LMRoman9-Regular;
	panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
	{font-family:LMRoman9-Italic;
	panose-1:0 0 0 0 0 0 0 0 0 0;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin-top:0cm;
	margin-right:0cm;
	margin-bottom:8.0pt;
	margin-left:0cm;
	line-height:107%;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
p.MsoNoSpacing, li.MsoNoSpacing, div.MsoNoSpacing
	{margin:0cm;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
	{margin-top:0cm;
	margin-right:0cm;
	margin-bottom:8.0pt;
	margin-left:36.0pt;
	line-height:107%;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst
	{margin-top:0cm;
	margin-right:0cm;
	margin-bottom:0cm;
	margin-left:36.0pt;
	line-height:107%;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle
	{margin-top:0cm;
	margin-right:0cm;
	margin-bottom:0cm;
	margin-left:36.0pt;
	line-height:107%;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast
	{margin-top:0cm;
	margin-right:0cm;
	margin-bottom:8.0pt;
	margin-left:36.0pt;
	line-height:107%;
	font-size:11.0pt;
	font-family:"Calibri",sans-serif;}
p.Code, li.Code, div.Code
	{mso-style-name:Code;
	mso-style-link:"Code Zchn";
	margin-top:6.0pt;
	margin-right:0cm;
	margin-bottom:6.0pt;
	margin-left:0cm;
	line-height:107%;
	font-size:9.0pt;
	font-family:"Courier New";}
p.CodeCxSpFirst, li.CodeCxSpFirst, div.CodeCxSpFirst
	{mso-style-name:CodeCxSpFirst;
	mso-style-link:"Code Zchn";
	margin-top:6.0pt;
	margin-right:0cm;
	margin-bottom:0cm;
	margin-left:0cm;
	line-height:107%;
	font-size:9.0pt;
	font-family:"Courier New";}
p.CodeCxSpMiddle, li.CodeCxSpMiddle, div.CodeCxSpMiddle
	{mso-style-name:CodeCxSpMiddle;
	mso-style-link:"Code Zchn";
	margin:0cm;
	line-height:107%;
	font-size:9.0pt;
	font-family:"Courier New";}
p.CodeCxSpLast, li.CodeCxSpLast, div.CodeCxSpLast
	{mso-style-name:CodeCxSpLast;
	mso-style-link:"Code Zchn";
	margin-top:0cm;
	margin-right:0cm;
	margin-bottom:6.0pt;
	margin-left:0cm;
	line-height:107%;
	font-size:9.0pt;
	font-family:"Courier New";}
span.CodeZchn
	{mso-style-name:"Code Zchn";
	mso-style-link:Code;
	font-family:"Courier New";}
span.Wording
	{mso-style-name:Wording;
	font-family:"Times New Roman",serif;
	color:black;
	font-weight:normal;}
.MsoPapDefault
	{margin-bottom:8.0pt;
	line-height:107%;}
@page WordSection1
	{size:595.3pt 841.9pt;
	margin:70.85pt 70.85pt 2.0cm 70.85pt;}
div.WordSection1
	{page:WordSection1;}
 /* List Definitions */
 ol
	{margin-bottom:0cm;}
ul
	{margin-bottom:0cm;}
-->
</style>

</head>

<body lang=EN-GB style='word-wrap:break-word'>

<div class=WordSection1>

<p class=MsoNoSpacing><a name="_Hlk105598784">Document number:&nbsp; P2601R</a>1</p>

<p class=MsoNoSpacing>Date: 2022-07-11</p>

<p class=MsoNoSpacing>Reply-to: Justin Cooke &lt;jgc@cems.de&gt;<br>
Target audience: EWG, CWG</p>

<p class=MsoNormal style='margin-top:6.0pt;line-height:normal'><b><span
style='font-size:12.0pt;font-family:"Times New Roman",serif'>&nbsp;</span></b></p>

<p class=MsoNormal><b><span style='font-size:12.0pt;line-height:107%'>Make
redundant empty angle brackets optional</span></b></p>

<p class=MsoNormal>&nbsp;</p>

<p class=MsoNormal><b>Proposal:</b> To make redundant empty angle brackets
optional for class and variable template argument lists.&nbsp; </p>

<p class=MsoNormal>&nbsp;</p>

<p class=MsoNormal><b>Revision history</b>:</p>

<p class=MsoNormal>R0: 2022-06-11</p>

<p class=MsoNormal>R1: (this revision):</p>

<p class=MsoListParagraphCxSpFirst style='margin-left:54.0pt;text-indent:-36.0pt'>(i)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>description amended to clarify that it refers both to class and variable
templates;</p>

<p class=MsoListParagraphCxSpMiddle style='margin-left:54.0pt;text-indent:-36.0pt'>(ii)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>description and wording amended to clarify the distinction between defaulted
and deduced template arguments;</p>

<p class=MsoListParagraphCxSpMiddle style='margin-left:54.0pt;text-indent:-36.0pt'>(iii)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span>additional examples included of where empty angle brackets can be
omitted without effect, and a counter-example where their presence/absence is
significant</p>

<p class=MsoListParagraphCxSpLast style='margin-left:54.0pt'>&nbsp;</p>

<p class=MsoNormal><b>Motivation:</b>&nbsp; Additional template parameters with
default arguments can be added to a class template declaration in a header file
without breaking code that uses the template. For example, early versions of <span
class=CodeZchn><span style='font-size:10.0pt;line-height:107%'>std::vector</span></span><span
style='font-size:14.0pt;line-height:107%'> </span>took just one parameter, the
value type; the allocator parameter was added later, with a default
argument.&nbsp; However, that upgrade pathway is currently only open where
there is already at least one template parameter. It is not currently possible
to replace a non-template class declaration by a class template, even with
default arguments for all parameters, without breaking most uses of the class,
because the syntax for using class templates requires empty angle brackets in
most circumstances, even where their omission would not result in ambiguity.
Since the introduction (in C++17) of CTAD, angle brackets can be omitted when
defining objects, but they are still required when declaring pointers,
references, arrays, external objects, function parameters, class members, base
classes, or template type parameters. The following examples illustrate the
current situation:</p>

<p class=CodeCxSpFirst>template &lt;typename T = int&gt; class C {};</p>

<p class=CodeCxSpMiddle><span lang=SV>C c;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//<i>OK&nbsp; (#1)</i></span></p>

<p class=CodeCxSpMiddle><span lang=SV>extern C x;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//<i>error: need</i> C&lt;&gt;</span></p>

<p class=CodeCxSpMiddle>C
*p;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//<i>error: need</i> C&lt;&gt;</p>

<p class=CodeCxSpMiddle>C
a[2];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//<i>error: need</i> C&lt;&gt;</p>

<p class=CodeCxSpMiddle>C &amp;r =
c;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//<i>error: need</i> C&lt;&gt;</p>

<p class=CodeCxSpMiddle>struct S { C c; };&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//<i>error: need</i> C&lt;&gt;</p>

<p class=CodeCxSpMiddle>struct D : C {};&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<i> error: need</i> C&lt;&gt;</p>

<p class=CodeCxSpMiddle>std::vector&lt;C&gt; v;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<i> error: need&nbsp; </i>C&lt;&gt;</p>

<p class=CodeCxSpLast>void foo(C c);&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<i> error: need</i>
C&lt;&gt;</p>

<p class=MsoNormal>The empty angle brackets are currently optional only in case
(#1) (CTAD).&nbsp; No ambiguity would arise from making them optional in all
the above cases, because names of class or variable templates must be unique
within a scope (13.1 <i>Note 5</i>).&nbsp; This change will allow class library
maintainers to upgrade existing class definitions to templates without breaking
user code.</p>

<p class=MsoNormal><b>&nbsp;</b></p>

<p class=MsoNormal><b>Description:  </b>The argument list for a class or variable
template can be empty when all arguments are defaulted or all arguments are defaulted
except for an empty argument for a trailing parameter pack.  This proposal makes
optional the angle brackets enclosing an empty class or variable template argument
list, except where the brackets are needed for disambiguation.  This is the
case for in initializing declarations, where use of a template name without an
argument list activates class template argument deduction (CTAD, 12.2.2.9).  This
proposal does not affect CTAD, but an example is included to illustrate how the
presence of angle brackets suppresses CTAD.  </p>

<p class=MsoNormal>The proposal does not affect function templates. However, in
declaring angle brackets to be optional for empty template argument lists in
general, the wording needs to mention that the brackets are still required to
disambiguate a function template from a non-template function with the same
name and scope.</p>

<p class=MsoNormal>The proposal does not affect template <i>parameter</i> lists,
where empty angle brackets disambiguate explicit full specialization
declarations (13.9.4) from explicit instantiation declarations (13.9.3).</p>

<p class=MsoNormal><b>&nbsp;</b></p>

<p class=MsoNormal><b>Effect on existing code</b>: None. Code using the proposed
feature is ill-formed under C++20 and earlier standards.</p>

<p class=MsoNormal style='margin-top:6.0pt;line-height:normal'><b><span
style='font-size:12.0pt;font-family:"Times New Roman",serif'>&nbsp;</span></b></p>

<p class=MsoNormal style='margin-top:6.0pt;line-height:normal'><b>Wording: </b>(edits
to N4910)</p>

<p class=MsoNormal style='margin-top:6.0pt;margin-right:0cm;margin-bottom:6.0pt;
margin-left:35.4pt;line-height:normal'><b><span style='font-size:12.0pt;
font-family:"Times New Roman",serif'>13.4.1</span></b><span style='font-size:
12.0pt;font-family:"Times New Roman",serif'>&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
style='font-size:10.0pt;font-family:"Times New Roman",serif'>&nbsp;<b>[temp.arg.general]</b></span></p>

<p class=MsoNormal style='margin-top:6.0pt;margin-right:0cm;margin-bottom:6.0pt;
margin-left:35.4pt;line-height:normal'><span style='font-size:12.0pt;
font-family:"Times New Roman",serif'>…</span></p>

<p class=MsoNormal style='margin-top:6.0pt;margin-right:0cm;margin-bottom:6.0pt;
margin-left:35.4pt;line-height:normal;text-autospace:none'><b><sup><span
style='font-size:12.0pt;font-family:"Times New Roman",serif'>5</span></sup></b><span
style='font-size:10.0pt;font-family:"Times New Roman",serif;color:black'> When
template argument packs or default </span><i><span style='font-size:10.0pt;
font-family:"Times New Roman",serif;color:#333333'>template-argument</span></i><span
style='font-size:10.0pt;font-family:"Times New Roman",serif;color:black'>s are
used, a </span><i><span style='font-size:10.0pt;font-family:"Times New Roman",serif;
color:#333333'>template-argument </span></i><span style='font-size:10.0pt;
font-family:"Times New Roman",serif;color:black'>list can be empty. In that
case the empty &lt;&gt; brackets <b><span style='background:lime'>may be
omitted</span></b> <s><span style='background:red'>shall <span
style='background:red'>still</span></span><span style='background:red'> be used</span><span
style='background:red'> as the </span></s></span><i><s><span style='font-size:
10.0pt;font-family:"Times New Roman",serif;color:#333333;background:red'>template-argument-list</span></s></i><i><s><span
style='font-size:10.0pt;font-family:"Times New Roman",serif;color:#333333'> </span></s></i><b><span
style='font-size:10.0pt;font-family:"Times New Roman",serif;color:#333333;
background:lime'>except where needed to disambiguate a class template specialization
with an empty argument list from a template name used as a placeholder for a
deduced class type (9.2.9.7) </span></b><span class=Wording><b><span
style='font-size:10.0pt;background:lime'>or</span></b></span><b><span
style='font-size:10.0pt;font-family:"Times New Roman",serif;color:black;
background:lime'> to</span></b><b><span style='font-size:10.0pt;font-family:
"Times New Roman",serif;color:black;background:lime'> disambiguate an
invocation of a function template specialization from an invocation of a
non-template function with the same name (13.10.<span style='background:lime'>2</span></span></b><span
class=Wording><b><span style='font-size:10.0pt;background:lime'>).</span></b></span></p>

<p class=MsoNormal style='margin-top:6.0pt;margin-right:0cm;margin-bottom:6.0pt;
margin-left:35.4pt;line-height:normal;text-autospace:none'><span
style='font-size:9.0pt;font-family:LMRoman9-Regular;color:black'>[</span><i><span
style='font-size:9.0pt;font-family:LMRoman9-Italic;color:black'>Example 5 </span></i><span
style='font-size:9.0pt;font-family:LMRoman9-Regular;color:black'>:</span></p>

<p class=CodeCxSpFirst style='margin-left:35.4pt'>template&lt;class T =
char&gt; class String;</p>

<p class=CodeCxSpMiddle style='margin-left:35.4pt'>String&lt;&gt;* p; //<i><span
style='font-family:LMRoman9-Italic'> OK, </span></i>String&lt;char&gt;</p>

<p class=CodeCxSpMiddle style='margin-left:35.4pt'>String* q; //<i><span
style='font-family:LMRoman9-Italic'> <s><span style='color:black;background:
red'>syntax <b>error</b></span></s><b> <span style='color:black;background:
lime'>OK, empty brackets &lt;&gt; omitted</span></b></span></i></p>

<p class=CodeCxSpMiddle style='margin-left:35.4pt'>&nbsp;</p>

<p class=CodeCxSpMiddle style='margin-left:35.4pt'>template&lt;class ...
Elements&gt; class Tuple;</p>

<p class=CodeCxSpMiddle style='margin-left:35.4pt'>Tuple&lt;&gt;* t; //<i><span
style='font-family:LMRoman9-Italic'> OK, </span></i>Elements <i><span
style='font-family:LMRoman9-Italic'>is empty</span></i></p>

<p class=CodeCxSpMiddle style='margin-left:35.4pt'>Tuple* u; //<i><span
style='font-family:LMRoman9-Italic'> <s><span style='color:black;background:
red'>syntax error</span></s> <b><span style='color:black;background:lime'>OK,
empty brackets &lt;&gt; omitted</span></b></span></i></p>

<p class=CodeCxSpMiddle style='margin-left:35.4pt'><b><span style='background:
lime'>&nbsp;</span></b></p>

<p class=CodeCxSpMiddle style='margin-left:35.4pt'><b><span style='background:
lime'>template &lt;class T = int&gt; struct C { C(T); };</span></b></p>

<p class=CodeCxSpMiddle style='text-indent:35.4pt'><b><span style='background:
lime'>std::vector&lt;C&gt; v&nbsp;;  //C&lt;int&gt;</span></b></p>

<p class=CodeCxSpMiddle style='text-indent:35.4pt'><b><span style='background:
lime'>struct S { C c; };&nbsp; &nbsp;&nbsp;//C&lt;int&gt;</span></b></p>

<p class=CodeCxSpMiddle style='text-indent:35.4pt'><b><span style='background:
lime'>struct D : C {};   //</span></b><b><i><span style='font-family:"Calibri",sans-serif;
background:lime'> </span></i><span style='background:lime'>C</span></b><b><span
style='background:lime'>&lt;int&gt;</span></b></p>

<p class=CodeCxSpMiddle style='text-indent:35.4pt'><b><span style='background:
lime'>void foo(C c);  //</span></b><b><i><span style='font-family:"Calibri",sans-serif;
background:lime'> </span></i><span style='background:lime'>C</span></b><b><span
style='background:lime'>&lt;int&gt;</span></b></p>

<p class=CodeCxSpMiddle style='margin-left:35.4pt'><b><span style='background:
lime'>C x = 1.0;  //</span></b><b><i><span style='font-family:"Calibri",sans-serif;
background:lime'>deduced to  </span></i><span style='background:lime'>C</span></b><b><i><span
style='font-family:"Calibri",sans-serif;background:lime'>&lt;</span></i><span
style='background:lime'>double&gt; </span></b><b><i><span style='font-family:
"Calibri",sans-serif;background:lime'>(see 12.2.2.9)</span></i></b></p>

<p class=CodeCxSpLast style='margin-left:35.4pt'><b><span style='background:
lime'>C&lt;&gt; y = 1.0; //C&lt;int&gt;, </span></b><b><i><span
style='font-family:"Calibri",sans-serif;background:lime'>initializer converted
to </span></i></b><span style='background:lime'>int</span><b><i><span
style='font-family:"Calibri",sans-serif;background:lime'> </span></i></b></p>

<p class=MsoNormal style='margin-top:6.0pt;margin-right:0cm;margin-bottom:6.0pt;
margin-left:35.4pt;line-height:normal'><i><span style='font-size:9.0pt;
font-family:LMRoman9-Italic;color:black'>—end example</span></i><span
style='font-size:9.0pt;font-family:LMRoman9-Regular;color:black'>]</span></p>

<p class=MsoNormal style='margin-top:6.0pt;margin-right:0cm;margin-bottom:6.0pt;
margin-left:35.4pt;line-height:normal'><span style='font-size:12.0pt;
font-family:"Times New Roman",serif'>&nbsp;</span></p>

</div>

</body>

</html>
