Richard Smith

Allow constant evaluation for all non-type template arguments


Change in 5.19 (expr.const) paragraph 3 and convert to a bulleted list:

[...] A converted constant expression of type T is an expression, implicitly converted to a prvalue of type T, where the converted expression is a core constant expression and the implicit conversion sequence contains only: and where the reference binding (if any) binds directly. [ Note: such expressions may be used in new expressions (5.3.4), as case expressions (6.4.2), as enumerator initializers if the underlying type is fixed (7.2), as array bounds (8.3.4), and as integral or enumeration non-type template arguments (14.3). — end note ]
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.

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

A template-argument for a non-type, non-template template-parameter shall be one of: For a non-type template-parameter 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): [ Note: If the template-argument represents a set of overloaded functions (or a pointer or member pointer to such), the matching function is selected from the set (13.4). ]

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

[ Note: A string literal (2.14.5) does not satisfy the requirements of any of these categories and thus is not an acceptable template-argument. [ Example: ... ] ]

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

[ Note: The address Addresses of an array elements and names or addresses of a non-static class data members are is not an acceptable template-arguments. [ Example:
template<int* p> class X { };

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

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

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

[ Note: Temporaries, unnamed lvalues, and named lvalues with no linkage are A temporary object is not an acceptable template-arguments when the corresponding template-parameter has reference type. [ Example: ... ] ]

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

The following conversions are performed on each expression used as a non-type template-argument. If a non-type template-argument cannot be converted to the type of the corresponding template-parameter then the program is ill-formed. [ Example: ... ]

Change in 14.4 (temp.type) paragraph 1:

Two template-ids refer to the same class, function, or variable if [ Example: ... ]