﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>

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

<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.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

blockquote pre em { font-family: normal }

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; }

</style>

<title>Allow constant evaluation for all non-type template arguments</title>
</head>
<body>

<div style="text-align: right; float: right">
<p>
ISO/IEC JTC1 SC22 WG21<br>
N4268<br>
Richard Smith<br>
richard@metafoo.co.uk<br>
2014-11-05
</div>

<h1>Allow constant evaluation for all non-type template arguments</h1>

<h2><a name="Wording">Wording</a></h2>

<p>
Change in 5.19 (expr.const) paragraph 3 and convert to a bulleted list:
<blockquote class="std">
  [...]
A <i>converted constant expression</i> of type <tt>T</tt> is an expression, implicitly
converted to <del>a prvalue of</del> type <tt>T</tt>,
where the converted expression is a <del>core</del>
constant expression and the implicit conversion sequence contains only<ins>:</ins>
<ul>
<li>user-defined conversions,
<li>lvalue-to-rvalue conversions (4.1),
<li><ins>array-to-pointer conversions (4.2),
<li><ins>function-to-pointer conversions (4.3),
<li><ins>qualification conversions (4.4),
<li>integral promotions (4.5), <del>and</del>
<li>integral conversions (4.7) other than narrowing conversions (8.5.4)<ins>,</ins>
<li><ins>null pointer conversions (4.10) from <tt>std::nullptr_t</tt>, and
<li><ins>null member pointer conversions (4.11) from <tt>std::nullptr_t</tt>,
</ul>
and where the reference binding (if any) binds directly</ins>.
[ <em>Note:</em> such expressions may be used in <tt>new</tt> expressions
(5.3.4), as <tt>case</tt> expressions (6.4.2), as enumerator initializers if
the underlying type is fixed (7.2), as array bounds (8.3.4), and as <del>integral or
  enumeration</del> non-type template arguments (14.3). — end note ]
</blockquote>

<em>Drafting note: previously, a converted constant expression could only be of integral or enumeration type, so these conversions do not change any existing uses of the term.</em>

<p>
Change in 14.3.2 (temp.arg.nontype) paragraph 1 and remove the bullets:

<blockquote class="std">
A <i>template-argument</i> for a non-type<del>, non-template</del> <i>template-parameter</i> shall be <del>one of:</del>
<ul>
<li><del>for a non-type <i>template-parameter</i> of integral or enumeration type,</del>
a converted constant expression (5.19) of the type of the
<i>template-parameter</i><ins>.</ins><del>; or</del>
<li><del>the name of a non-type <i>template-parameter</i>; or</del>
<li><del>a constant expression (5.19) that designates the address of a complete object
<del>with static storage duration and external or internal linkage or a
function with external or internal linkage, including function
templates and function <i>template-ids</i> but excluding non-static class members, expressed
(ignoring parentheses) as <tt>&</tt> <i>id-expression</i>, where the <i>id-expression</i>
is the name of an object or function, except that the <tt>&</tt> may be omitted if the
name refers to a function or array and shall be omitted if the corresponding
<i>template-parameter</i> is a reference; or</del>
<li><del>a constant expression that evaluates to a null pointer value (4.10); or</del>
<li><del>a constant expression that evaluates to a null member pointer value (4.11); or</del>
<li><del>a pointer to member expressed as described in 5.3.1; or</del>
<li><del>a constant expression of type <tt>std::nullptr_t</tt></del>.
</ul>
<ins>For a non-type <i>template-parameter</i> of reference or pointer type, the
  value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
  <ul><li>a subobject (1.8),
      <li>a temporary object (12.2),
      <li>a string literal (2.14.5),
      <li>the result of a <tt>typeid</tt> expression (5.2.8), or
      <li>a predefined <tt>__func__</tt> variable (8.4.1).
  </ul>
  [ <em>Note:</em> If the <i>template-argument</i> represents a set of overloaded functions (or a pointer or member pointer to such), the matching function is selected from the set (13.4). ]</ins>
</blockquote>

<p>Change in 14.3.2 (temp.arg.nontype) paragraph 2:

<blockquote class="std">
[ <i>Note:</i> A string literal (2.14.5) <del>does not satisfy the requirements
  of any of these categories and thus</del> is not an acceptable
  <i>template-argument</i>.
[ <i>Example:</i> ... ] ]
</blockquote>

<p>Change in 14.3.2 (temp.arg.nontype) paragraph 3:

<blockquote class="std">
[ <em>Note:</em>
<ins>The address</ins>
<del>Addresses</del>
of <ins>an</ins> array element<del>s and names</del> or <del>addresses of a</del> non-static <del>class</del> <ins>data</ins> member<del>s are</del> <ins>is</ins> not <ins>an</ins> acceptable
<i>template-argument</i><del>s</del>.
[ <em>Example:</em>
<pre class="example">
template&lt;int* p> class X { };

int a[10];
struct S { int m; static int s; } s;

X&lt;&a[2]> x3; // error: address of array element
X&lt;&s.m> x4;  // error: address of non-static member
X&lt;&s.s> x5;  // <del>error: &S::s must be used</del> <ins>OK: address of static member</ins>
X&lt;&S::s> x6; // OK: address of static member
</pre>
] ]
</blockquote>

<p>Change in 14.3.2 (temp.arg.nontype) paragraph 4:

<blockquote class="std">
[ <em>Note:</em>
<del>Temporaries, unnamed lvalues, and named lvalues with no linkage are</del>
<ins>A temporary object is</ins>
not <ins>an</ins> acceptable
<i>template-argument</i><del>s</del> when the corresponding <i>template-parameter</i> has reference type. [ <em>Example:</em> ... ] ]
</blockquote>

<p>Delete all of 14.3.2 (temp.arg.nontype) paragraph 5 other than its example and move it to before paragraph 2:

<blockquote class="std">
  <del>The following conversions are performed on each expression used as a non-type <em>template-argument</em>. If a non-type <em>template-argument</em> cannot be converted to the type of the corresponding <em>template-parameter</em> then the program is ill-formed.
<ul><li>...</ul>
</del>
[ <em>Example:</em> ... ]
</blockquote>

<p>Change in 14.4 (temp.type) paragraph 1:

<blockquote class="std">
Two <i>template-id</i>s refer to the same class, function, or variable if
<ul>
<li>their <i>template-name</i>s, <i>operator-function-id</i>s, or <i>literal-operator-id</i>s refer to the same template and
<li>their corresponding type <i>template-argument</i>s are the same type and
<li>their corresponding non-type template arguments of integral or enumeration type have identical values and
<li>their corresponding non-type template-arguments of pointer type refer to the same <del>external</del> object or
    function or are both the null pointer value and
<li>their corresponding non-type template-arguments of pointer-to-member type refer to the same class
    member or are both the null member pointer value and
<li>their corresponding non-type template-arguments of reference type refer to the same <del>external</del> object
    or function and
<li>their corresponding template template-arguments refer to the same template.
</ul>
[ <em>Example:</em> ... ]
</blockquote>
