<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">
<title>Declaring non-type template parameters with auto</title>

<style type="text/css">

body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.std del { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC; }
blockquote.std ins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5em padding-right: 0.5em; }
blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3;
  padding-left: 0.5em; padding-right: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }

table.frontmatter { border: 0;  margin: 0; }

ul.dash { list-style-type: none; }
ul.dash li:before { content: '\2014'; margin-left: -1em }

span.highlight { background-color: #7FDFFF }

</style>

<script type="text/javascript" src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</head>

<body>
<h1>Declaring non-type template parameters with <code class="prettyprint">auto</code></h1>
<table class="frontmatter" border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" width="619">
    <tr>
        <td align="left" valign="top">Document number:</td>
        <td>P0127R2</td>
    </tr>
    <tr>
        <td align="left" valign="top">Date:</td>
        <td>2016-06-23</td>
    </tr>
    <tr>
        <td align="left" valign="top">Project:</td>
        <td>Programming Language C++, Evolution Working Group</td>
    </tr>
    <tr>
        <td align="left" valign="top">Revises:</td>
        <td><a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0127r1.html">P0127R1</a></td>
    </tr>
    <tr>
        <td align="left" valign="top">Reply-to:</td>
        <td>James Touton &lt;<a href="mailto:bekenn@gmail.com">bekenn@gmail.com</a>&gt;<br>
        Mike Spertus, Symantec &lt;<a href="mailto:mike_spertus@symantec.com">mike_spertus@symantec.com</a>&gt;</td>
    </tr>
</table>

<h2><a id="TableOfContents">Table of Contents</a></h2>
<ol>
    <li><a href="#TableOfContents">Table of Contents</a></li>
    <li><a href="#WhatsNew">What's New</a></li>
    <li><a href="#Introduction">Introduction</a></li>
    <li><a href="#FeatureTestMacro">Feature Test Macro</a></li>
    <li><a href="#Wording">Wording</a></li>
    <li><a href="#Acknowledgments">Acknowledgments</a></li>
</ol>

<h2><a id="WhatsNew">What's New</a></h2>
<h3>Changes since P0127R1</h3>
<ul>
<li>Updated standardese and removed detailed design overview.</li>
</ul>

<h2><a id="Introduction">Introduction</a></h2>
<p>This paper proposes allowing non-type template parameters to be declared with the <code class="prettyprint">auto</code> placeholder type specifier.
For a detailed discussion of the feature and design decisions, see <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0127r1.html">P0127R1</a>.</p>

<p>Example:</p>
<pre class="example">
<code class="prettyprint">template &lt;auto v&gt; struct S;  // <em>type of v is deduced</em></code>
</pre>

<h2><a id="FeatureTestMacro">Feature Test Macro</a></h2>
<p>The recommended feature test macro is <code>__cpp_template_auto</code>.

<h2><a id="Wording">Wording</a></h2>
<p>All modifications are presented relative to N4594.</p>

<p>Modify &sect;7.1.6.4 [dcl.spec.auto] paragraph 5:</p>
<blockquote class="std">
<p>A placeholder type can also be used in declaring a variable in the <var>condition</var> of a selection statement (6.4) or an iteration statement (6.5),
in the <var>type-specifier-seq</var> in the <var>new-type-id</var> or <var>type-id</var> of a <var>new-expression</var> (5.3.4),
in a <var>for-range-declaration</var>,
<del>and </del>in declaring a static data member with a <var>brace-or-equal-initializer</var> that appears within the <var>member-specification</var> of a class definition (9.4.2)<ins>,
and as a <var>decl-specifier</var> of the <var>parameter-declaration</var>'s <var>decl-specifier-seq</var> in a <var>template-parameter</var> (14.1)</ins>.</p>
</blockquote>

<p>Delete &sect;7.1.6.4 [dcl.spec.auto] paragraph 7.
(The rules specified in this paragraph are reformulated below as &sect;7.1.6.4.1 [dcl.auto.deduct])</p>
<blockquote class="stddel">
<p>When a variable declared using a placeholder type is initialized, or a return statement occurs in a function
declared with a return type that contains a placeholder type, the deduced return type or variable type is
determined from the type of its initializer. [...]</p>
</blockquote>

<p>Modify &sect;7.1.6.4 [dcl.spec.auto] paragraph 8 (now paragraph 7):</p>
<blockquote class="std">
<p>If the <var>init-declarator-list</var> contains more than one <var>init-declarator</var>, they shall all form declarations of variables.
The type of each declared variable is determined <del>as described above</del><ins>by placeholder type deduction (7.1.6.4.1)</ins>, and if the type that replaces the placeholder type is not the same in each deduction, the program is ill-formed.</p>
<p>[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>  auto x = 5, *y = &amp;x;        // <em>OK: </em>auto<em> is </em>int
  auto a = 5, b = { 1, 2 };   // <em>error: different types for </em>auto</code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<p>Add a new section &sect;7.1.6.4.1 [dcl.auto.deduct] with paragraphs as follows (highlighted text denotes meaningful changes from the deleted &sect;7.1.6.4 paragraph 7):</p>

<blockquote class="std">
<p><span class="highlight"><var>Placeholder type deduction</var> is the process by which a type containing a placeholder type is replaced by a deduced type.</span></p>
</blockquote>

<blockquote class="std">
<p><span class="highlight">A type <code>T</code> containing a placeholder type, and a corresponding initializer <code>e</code>, are determined as follows:</span></p>
<ul class="dash">
<li>for a <code>return</code> statement that occurs in a function declared with a return type that contains a placeholder type, <code>T</code> is the declared return type and <code>e</code> is the operand of the return statement.
If the <code>return</code> statement has no operand, then <code>e</code> is <code>void{}</code>;</li>
<li>for a variable declared with a type that contains a placeholder type, <code>T</code> is the declared type of the variable and <code>e</code> is the initializer.
If the initialization is direct-list-initialization, the initializer shall be a <var>braced-init-list</var> containing only a single <var>assignment-expression</var> and <code>e</code> is the <var>assignment-expression</var>;</li>
<li><span class="highlight">for a non-type template parameter declared with a type that contains a placeholder type, <code>T</code> is the declared type of a non-type template parameter and <code>e</code> is a corresponding template argument.</span></li>
</ul>
<p>In the case of a <code>return</code> statement with no operand or with an operand of type <code>void</code>:</p>
<ul>
<li>if the placeholder is <code>decltype(auto)</code>, then <code>T</code> shall be <code>decltype(auto)</code>;</li>
<li>otherwise, <code>T</code> shall be <var>cv</var> <code>auto</code>.</li>
</ul>
</blockquote>

<blockquote class="std">
<p>If the deduction is for a return statement and <code>e</code> is a <var>braced-init-list</var> (8.5.4), the program is ill-formed.</p>
</blockquote>

<blockquote class="std">
<p>If the placeholder is the <code>auto</code> <var>type-specifier</var>, the deduced type <code>T'</code> replacing <code>T</code> is determined using the rules for template argument deduction.
Obtain <code>P</code> from <code>T</code> by replacing the occurrences of <code>auto</code> with either a new invented type template parameter <code>U</code> or, if the initialization is copy-list-initialization, with <code>std::initializer_list&lt;U&gt;</code>.
Deduce a value for <code>U</code> using the rules of template argument deduction from a function call (14.8.2.1), where <code>P</code> is a function template parameter type and the corresponding argument is <code>e</code>.
If the deduction fails, the declaration is ill-formed.
Otherwise, <code>T'</code> is obtained by substituting the deduced <code>U</code> into <code>P</code>.
[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>  auto x1 = { 1, 2 };       // decltype(x1) <em>is</em> std::initializer_list&lt;int&gt;
  auto x2 = { 1, 2.0 };     // <em>error: cannot deduce element type</em>
  auto x3{ 1, 2 };          // <em>error: not a single element</em>
  auto x4 = { 3 };          // decltype(x4) <em>is</em> std::initializer_list&lt;int&gt;
  auto x5{ 3 };             // decltype(x5) <em>is</em> int</code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>

<p>[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>  const auto&amp; i = expr;</code>
</pre>
<p>The type of <code>i</code> is the deduced type of the parameter <code>u</code> in the call <code>f(expr)</code> of the following invented function template:</p>
<pre class="example">
  <code>template &lt;class U&gt; void f(const U&amp; u);</code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<blockquote class="std">
<p>If the placeholder is the <code>decltype(auto)</code> <var>type-specifier</var>, <code>T</code> shall be the placeholder alone.
The type deduced for <code>T</code> is determined as described in 7.1.6.2, as though <code>e</code> had been the operand of the <code>decltype</code>.
[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>int i;
int&amp;&amp; f();
auto            x2a(i);          // decltype(x2a) <em>is</em> int
decltype(auto)  x2d(i);          // decltype(x2d) <em>is</em> int
auto            x3a = i;         // decltype(x3a) <em>is</em> int
decltype(auto)  x3d = i;         // decltype(x3d) <em>is</em> int
auto            x4a = (i);       // decltype(x4a) <em>is</em> int
decltype(auto)  x4d = (i);       // decltype(x4d) <em>is</em> int&amp;
auto            x5a = f();       // decltype(x5a) <em>is</em> int
decltype(auto)  x5d = f();       // decltype(x5d) <em>is</em> int&amp;&amp;
auto            x6a = { 1, 2 };  // decltype(x6a) <em>is</em> std::initializer_list&lt;int&gt;
decltype(auto)  x6d = { 1, 2 };  // <em>error,</em> { 1, 2 } <em>is not an expression</em>
auto*           x7a = &amp;i;        // decltype(x7a) <em>is</em> int*
decltype(auto)* x7d = &amp;i;        // <em>error, declared type is not plain</em> decltype(auto)</code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<p>Modify &sect;14.1 [temp.param] paragraph 4:</p>
<blockquote class="std">
<p>A non-type <var>template-parameter</var> shall have one of the following (optionally <var>cv-qualified</var>) types:</p>
<ul class="dash">
<li>integral or enumeration type,</li>
<li>pointer to object or pointer to function,</li>
<li>lvalue reference to object or lvalue reference to function,</li>
<li>pointer to member,</li>
<li><code>std::nullptr_t</code><del>.</del><ins>,</ins></li>
<li><ins>a type that contains a placeholder type (7.1.6.4).</ins></li>
</ul>
</blockquote>

<p>Insert a new paragraph before &sect;14.3.2 [temp.arg.nontype] paragraph 1:</p>
<blockquote class="stdins">
<p>If the type of a <var>template-parameter</var> contains a placeholder type (7.1.6.4, 14.1), the deduced parameter type is determined from the type of the <var>template-argument</var> by placeholder type deduction (7.1.6.4.1).
If a deduced parameter type is not permitted for a <var>template-parameter</var> declaration (14.1), the program is ill-formed.</p>
</blockquote>

<p>Modify &sect;14.3.2 [temp.arg.nontype] paragraph 2:</p>
<blockquote class="std">
<p>[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>template&lt;const int* pci&gt; struct X { /* <em>...</em> */ };
int ai[10];
X&lt;ai&gt; xi; // <em>array to pointer and qualification conversions</em>

struct Y { /* <em>...</em> */ };
template&lt;const Y&amp; b&gt; struct Z { /* <em>...</em> */ };
Y y;
Z&lt;y&gt; z; // <em>no conversion, but note extra cv-qualification</em>

template&lt;int (&amp;pa)[5]&gt; struct W { /* <em>...</em> */ };
int b[5];
W&lt;b&gt; w; // <em>no conversion</em>

void f(char);
void f(int);

template&lt;void (*pf)(int)&gt; struct A { /* <em>...</em> */ };
A&lt;&amp;f&gt; a; // <em>selects f(int)</em>
<ins>
template&lt;auto n&gt; struct B { /* <em>...</em> */ };
B&lt;5&gt; b1;   // <em>OK: template parameter type is int</em>
B&lt;'a'&gt; b2; // <em>OK: template parameter type is char</em>
B&lt;2.5&gt; b3; // <em>error: template parameter type cannot be double</em></ins></code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<p>Remove the original &sect;14.5.5.1 [temp.class.spec.match] paragraph 3 (this paragraph is superfluous):</p>
<blockquote class="stddel">
<p>A non-type template argument can also be deduced from the value of an actual template argument of a non-type parameter of the primary template. [&nbsp;<i>Example:</i> the declaration of <code>a2</code> above. &mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<p>Remove &sect;14.5.5 [temp.class.spec] paragraph 8 list item 8.1 from the bulleted list and insert it as a new paragraph after 14.5.5.1 [temp.class.spec.match] paragraph 3 with the modifications shown:</p>
<blockquote class="std">
<p><del>Each <var>template-parameter</var> shall appear at least once in the <var>template-id</var> outside a non-deduced context.</del>
<ins>If the template arguments of a partial specialization cannot be deduced because of the structure of its <var>template-parameter-list</var> and the <var>template-id</var>, the program is ill-formed.</ins>
[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>template &lt;int I, int J&gt; struct A {};
template &lt;int I&gt; struct A&lt;I+5, I*2&gt; {};    // <em>error</em>

template &lt;int I&gt; struct A&lt;I, I&gt; {};        // <em>OK</em>

template &lt;int I, int J, int K&gt; struct B {};
template &lt;int I&gt; struct B&lt;I, I*2, 2&gt; {};   // <em>OK</em></code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<p>Modify &sect;14.6.2.2 [temp.dep.expr] paragraph 3:</p>
<blockquote class="std">
<p>An <var>id-expression</var> is type-dependent if it contains</p>
<ul class="dash">
<li>an <var>identifier</var> associated by name lookup with one or more declarations declared with a dependent type,</li>
<li><ins>an <var>identifier</var> associated by name lookup with a non-type <var>template-parameter</var> declared with a type that contains a placeholder type (7.1.6.4),</ins></li>
<li>an <var>identifier</var> associated by name lookup with one or more declarations of member functions of the current instantiation declared with a return type that contains a placeholder type<del> (7.1.6.4)</del>,</li>
<li>the <var>identifier</var> <code>__func__</code> (8.4.1), where any enclosing function is a template, a member of a class template, or a generic lambda,</li>
<li>a <var>template-id</var> that is dependent,</li>
<li>a <var>conversion-function-id</var> that specifies a dependent type, or</li>
<li>a <var>nested-name-specifier</var> or a <var>qualified-id</var> that names a member of an unknown specialization;</li>
</ul>
<p>or if it names a dependent member of the current instantiation that is a static data member of type &ldquo;array of unknown bound of T&rdquo; for some T (14.5.1.3).
Expressions of the following forms are type-dependent only if the type specified by the <var>type-id</var>, <var>simple-type-specifier</var> or <var>new-type-id</var> is dependent, even if any subexpression is type-dependent:</p>
<dl>
<dd><var>simple-type-specifier</var> <code>(</code> <var>expression-list<sub>opt</sub></var> <code>)</code></dd>
<dd><code>::</code><var><sub>opt</sub></var> <code>new</code> <var>new-placement<sub>opt</sub></var> <var>new-type-id</var> <var>new-initializer<sub>opt</sub></var></dd>
<dd><code>::</code><var><sub>opt</sub></var> <code>new</code> <var>new-placement<sub>opt</sub></var> <code>(</code> <var>type-id</var> <code>)</code> <var>new-initializer<sub>opt</sub></var></dd>
<dd><code>dynamic_cast</code> <code>&lt;</code> <var>type-id</var> <code>&gt;</code> <code>(</code> <var>expression</var> <code>)</code></dd>
<dd><code>static_cast</code> <code>&lt;</code> <var>type-id</var> <code>&gt;</code> <code>(</code> <var>expression</var> <code>)</code></dd>
<dd><code>const_cast</code> <code>&lt;</code> <var>type-id</var> <code>&gt;</code> <code>(</code> <var>expression</var> <code>)</code></dd>
<dd><code>reinterpret_cast</code> <code>&lt;</code> <var>type-id</var> <code>&gt;</code> <code>(</code> <var>expression</var> <code>)</code></dd>
<dd><code>(</code> <var>type-id</var> <code>)</code> <var>cast-expression</var></dd>
</dl>
</blockquote>

<p>Modify &sect;14.5.5.2 [temp.class.order] paragraph 1:</p>
<blockquote class="std">
<p>For two class template partial specializations, the first is more specialized than the second if, given the following rewrite to two function templates, the first function template is more specialized than the second according to the ordering rules for function templates (14.5.6.2):</p>
<ul class="dash">
<li><del>the first</del><ins>each of the two</ins> function template<ins>s</ins> has the same template parameters as <del>the first</del><ins>its corresponding</ins> partial specialization<del> and</del><ins>.
Each function template also</ins> has a single function parameter whose type is a class template specialization <del>with</del><ins>where</ins> the template arguments <del>of the first partial specialization</del><ins> are the corresponding template parameters from the function template for each template argument in the <var>template-argument-list</var> of the <var>simple-template-id</var> of the partial specialization</ins><del>, and</del><ins>.</ins></li>
<li><del>the second function template has the same template parameters as the second partial specialization
and has a single function parameter whose type is a class template specialization with the template
arguments of the second partial specialization.</del></li>
</ul>
</blockquote>

<p>Modify &sect;14.5.5.2 [temp.class.order] paragraph 2:</p>
<blockquote class="std">
<p>[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>template &lt;int I, int J, class T&gt; class X { };
template &lt;int I, int J&gt;          class X&lt;I, J, int&gt; { }; // <em>#1</em>
template &lt;int I&gt;                 class X&lt;I, I, int&gt; { }; // <em>#2</em>

template &lt;int I<ins>0</ins>, int J<ins>0</ins>&gt; void f(X&lt;I<ins>0</ins>, J<ins>0</ins>, int&gt;); // <em>A</em>
template &lt;int I<ins>0</ins>&gt;         void f(X&lt;I<ins>0</ins>, I<ins>0</ins>, int&gt;); // <em>B</em>
<ins>
template &lt;auto v&gt;    class Y { };
template &lt;auto* p&gt;   class Y&lt;p&gt; { };  // <em>#3</em>
template &lt;auto** pp&gt; class Y&lt;pp&gt; { }; // <em>#4</em>

template &lt;auto* p0&gt;   void g(Y&lt;p0&gt;);  // <em>C</em>
template &lt;auto** pp0&gt; void g(Y&lt;pp0&gt;); // <em>D</em></ins>
</code>
</pre>
<p><del>The partial specialization #2 is more specialized than the partial specialization #1 because</del><ins>According to the ordering rules for function templates,</ins> the function template <code>B</code> is more specialized than the function template <code>A</code> <del>according to the ordering rules for function templates</del><ins>and the function template <code>D</code> is more specialized than the function template <code>C</code>.
Therefore, the partial specialization #2 is more specialized than the partial specialization #1 and the partial specialization #4 is more specialized than the partial specialization #3</ins>. &mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<p>Modify &sect;14.5.6.2 [temp.func.order] paragraph 3:</p>
<blockquote class="std">
<p>To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs (14.5.3) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.
<ins>[&nbsp;<i>Note:</i> the type replacing the placeholder in the type of the value synthesized for a non-type template parameter is also a unique synthesized type. &mdash;<i>end note</i>&nbsp;]</ins></p>
</blockquote>

<p>Modify &sect;14.8.2.5 [temp.deduct.type] paragraph 2:</p>
<blockquote class="std">
<p>In some cases, the deduction is done using a single set of types P and A, in other cases, there will be a set of corresponding types P and A.
Type deduction is done independently for each P/A pair, and the deduced template argument values are then combined.
If type deduction cannot be done for any P/A pair, or if for any pair the deduction leads to more than one possible set of deduced values, or if different pairs yield different deduced values, or if any template argument remains neither deduced nor explicitly specified, template argument deduction fails.
<ins>The type of a type parameter is only deduced from an array bound if it is not otherwise deduced.</ins></p>
</blockquote>

<p>Replace &sect;14.8.2.5 [temp.deduct.type] paragraph 13 with the following paragraph:</p>
<blockquote class="stddel">
<p>A template type argument cannot be deduced from the type of a non-type <var>template-argument</var>.</p>
</blockquote>
<blockquote class="stdins">
<p>When the value of the argument corresponding to a non-type template parameter <code>P</code> that is declared with a dependent type is deduced from an expression, the template parameters in the type of <code>P</code> are deduced from the type of the value.

[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>template &lt;long n&gt; struct A { };

template &lt;class T&gt; struct C;
template &lt;class T, T n&gt; struct C&lt;A&lt;n&gt;&gt;
{
    using Q = T;
};

typedef long R;
typedef C&lt;A&lt;2&gt;&gt;::Q R;  // <em>OK; </em>T<em> was deduced to </em>long<em> from the template argument value in the type </em>A&lt;2&gt;</code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>

<p>The type of <code>N</code> in the type <code>T[N]</code> is <code>std::size_t</code>. [&nbsp;<i>Example:</i></p>
<pre class="example">
<code>template &lt;typename T&gt; struct S;
template &lt;typename T, T n&gt; struct S&lt;int[n]&gt; {
    using Q = T;
};

typedef S&lt;int[42]&gt;::Q V;
typedef decltype(sizeof 0) V;  // <em>OK; </em>T<em> was deduced to </em>std::size_t<em> from the type </em>int[42]</code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<p>Modify &sect;14.8.2.5 [temp.deduct.type] paragraph 14:</p>
<blockquote class="std">
<p>[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>template&lt;class T, T i&gt; void f(int <del>a[10]</del><ins>(&amp;a)</ins>[i]);
int v[10]<del>[20]</del>;
f(v); // <del><em>error: argument for template-parameter T cannot be deduced</em></del><ins><em>OK: </em>T<em> is </em>std::size_t</ins></code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<p>Insert a new section "Clause 14: templates" [diff.cpp14.temp] before &sect;C.4.5 [diff.cpp14.string]:</p>
<blockquote class="stdins">
<p>14.8.2.5 [temp.deduct.type]<br>
<strong>Change:</strong> Allowance to deduce from the type of a non-type template argument.<br>
<strong>Rationale:</strong> In combination with the ability to declare non-type template arguments with placeholder types, allows partial specializations to decompose from the type deduced for the non-type template argument.<br>
<strong>Effect on original feature:</strong> Valid C++ 2014 code may fail to compile or produce different results in this International Standard:</p>
<pre class="example">
<code>template &lt;int N&gt; struct A;
template &lt;typename T, T N&gt; int foo(A&lt;N&gt; *) = delete;
void foo(void *);
void bar(A&lt;0&gt; *p) {
  foo(p); // <em>ill-formed; previously well-formed</em>
}</code>
</pre>
</blockquote>

<h2><a id="Acknowledgments">Acknowledgments</a></h2>
<p>Numerous people gave constructive feedback regarding the use of <code class="prettyprint">auto</code> in template parameter lists in an <a href="http://isocpp.org/">isocpp.org</a> discussion <a href="https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/cqaS7PcU5Qc">thread</a>.</p>

<p>Special thanks to Mike Spertus and Gabriel dos Reis for their invaluable analysis and assistance.</p>

<p>Thanks also to Andrew Sutton for assistance and instruction in identifying potential areas of conflict with the Concepts TS, and to Hubert Tong for essential contributions to the wording.</p>

</body></html>
