[temp.arg.nontype] (original) (raw)
13 Templates [temp]
13.4 Template arguments [temp.arg]
13.4.3 Constant template arguments [temp.arg.nontype]
A template argument E for a constant template parameter with declared type Tshall be such that the invented declarationT 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.
If the parameter type thus deduced is not permitted for a constant template parameter ([temp.param]), the program is ill-formed.
The value of a constant template parameter Pof (possibly deduced) type Tis determined from its template argument A as follows.
If T is not a class type andA 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).
Otherwise, a temporary variableconstexpr T v = A;is introduced.
The lifetime of v ends immediately after initializing it and any template parameter object (see below).
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,
- the initialization would be ill-formed, or
- the full-expression of an invented init-declaratorfor the initialization would not be a constant expression when interpreted as a constant-expression ([expr.const]), or
- the initialization would cause P to not be template-argument-equivalent ([temp.type]) to v,
the program is ill-formed.
Otherwise, the value of P is that of v.
For a constant template parameter of reference or pointer type, or for each non-static data member of reference or pointer type in a constant template parameter of class type or subobject thereof, the reference or pointer value shall not refer or point to (respectively):
- a temporary object ([class.temporary]),
- a string literal object ([lex.string]),
- the result of a typeid expression ([expr.typeid]),
- a predefined __func__ variable ([dcl.fct.def.general]), or
- a subobject ([intro.object]) of one of the above.
[Example 1: template <int& r> class A{};extern int x; A<x> a; void f(int p) { constexpr int& r = p; A<r> a; } — _end example_]
[Example 2: template<const int* pci> struct X { };int ai[10]; X<ai> xi; struct Y { };template<const Y& b> struct Z { }; Y y; Z<y> z; template<int (&pa)[5]> struct W { };int b[5]; W<b> w; void f(char);void f(int);template<void (*pf)(int)> struct A { }; A<&f> a; template<auto n> struct B { }; B<5> b1; B<'a'> b2; B<2.5> b3; B<void(0)> b4; template<int i> struct C { }; C<{ 42 }> c1; struct J1 { J1 *self = this;}; B<J1{}> j1; struct J2 { J2 *self = this;constexpr J2() {} constexpr J2(const J2&) {} }; B<J2{}> j2; — _end example_]
[Note 2:
[Example 3: template<class T, T p> class X { }; X<const char*, "Studebaker"> x; X<const char*, "Knope" + 1> x2; const char p[] = "Vivisectionist"; X<const char*, p> y; struct A { constexpr A(const char*) {} }; X<A, "Pyrophoricity"> z; — _end example_]
— _end note_]
[Note 3:
A temporary object is not an acceptabletemplate-argumentwhen the corresponding template parameter has reference type.
[Example 4: template<const int& CRI> struct B { }; B<1> b1; int c = 1; B<c> b2; struct X { int n; };struct Y { const int &r; };template<Y y> struct C { }; C<Y{X{1}.n}> c; — _end example_]
— _end note_]