A template argument E for
a non-type template-parameter with declared type T
shall be such that the invented declaration
T x =E ;
satisfies the semantic constraints for the definition of
a constexpr variable with static storage duration ([dcl.constexpr]).
If T contains a placeholder type ([dcl.spec.auto])
or a placeholder for a deduced class type ([dcl.type.class.deduct]),
the type of the parameter is deduced from the above declaration.
The value of a non-type template-parameterP
of (possibly deduced) type T
is determined from its template argument A as follows.
If T is not a class type and
A is not a braced-init-list,
A shall be a converted constant expression ([expr.const])
of type T; the value of P is A (as converted).
If T is a class type,
a template parameter object ([temp.param]) exists
that is constructed so as to be template-argument-equivalent to v;
P denotes that template parameter object.
P is copy-initialized from an unspecified candidate initializer
that is template-argument-equivalent to v.
If, for the initialization from any candidate initializer,
For a non-type template-parameter of reference or pointer type,
or for each non-static data member of reference or pointer type
in a non-type template-parameter of class type or subobject thereof,
the reference or pointer value shall not refer
or point to (respectively):
[Example 1: template<int& r>class A{};
externint x;
A<x> a; // OKvoid f(int p){constexprint& r = p; // OK
A<r> a; // error: a static constexpr int& variable cannot be initialized to refer to p here} — end example]
[Example 2: template<constint* pci>struct X {/* ... */};
int ai[10];
X<ai> xi; // array to pointer and qualification conversionsstruct Y {/* ... */};
template<const Y& b>struct Z {/* ... */};
Y y;
Z<y> z; // no conversion, but note extra cv-qualificationtemplate<int(&pa)[5]>struct W {/* ... */};
int b[5];
W<b> w; // no conversionvoid f(char);
void f(int);
template<void(*pf)(int)>struct A {/* ... */};
A<&f> a; // selects f(int)template<auto n>struct B {/* ... */};
B<5> b1; // OK, template parameter type is int
B<'a'> b2; // OK, template parameter type is char
B<2.5> b3; // OK, template parameter type is double
B<void(0)> b4; // error: template parameter type cannot be voidtemplate<int i>struct C {/* ... */};
C<{42}> c1; // OKstruct J1 {
J1 *self =this;
};
B<J1{}> j1; // error: initialization of template parameter object is not a constant expressionstruct J2 {
J2 *self =this;
constexpr J2(){}constexpr J2(const J2&){}};
B<J2{}> j2; // error: template parameter object not template-argument-equivalent to introduced temporary — end example]
[Example 4: template<constint& CRI>struct B {/* ... */};
B<1> b1; // error: temporary would be required for template argumentint c =1;
B<c> b2; // OKstruct X {int n; };
struct Y {constint&r; };
template<Y y>struct C {/* ... */};
C<Y{X{1}.n}> c; // error: subobject of temporary object used to initialize// reference member of template parameter — end example]