[temp.arg.nontype]

# 13 Templates [[temp]](./#temp)

## 13.4 Template arguments [[temp.arg]](temp.arg#nontype)

### 13.4.3 Constant template arguments [temp.arg.nontype]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1233)

A template argument E for
a constant template parameter with declared type T shall 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]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers"))[.](#1.sentence-1)

If T contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))
or a placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced class template specialization types")),
the type of the parameter is deduced from the above declaration[.](#1.sentence-2)

[*Note [1](#note-1)*:

E is a [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") or
(for a default template argument) an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")[.](#1.sentence-3)

â *end note*]

If the parameter type thus deduced is not permitted
for a constant template parameter ([[temp.param]](temp.param "13.2 Template parameters")),
the program is ill-formed[.](#1.sentence-4)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1253)

The value of a constant template parameter P of (possibly deduced) type T is determined from its template argument A as follows[.](#2.sentence-1)

If T is not a class type andA is not a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]"),A shall be a converted constant expression ([[expr.const]](expr.const "7.7 Constant expressions"))
of type T; the value of P is A (as converted)[.](#2.sentence-2)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1262)

Otherwise, a temporary variableconstexpr T v = A; is introduced[.](#3.sentence-1)

The lifetime of v ends immediately after initializing it and
any template parameter object (see below)[.](#3.sentence-2)

For each such variable,
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") v is termed a [*candidate initializer*](#def:candidate_initializer "13.4.3 Constant template arguments [temp.arg.nontype]")[.](#3.sentence-3)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1274)

If T is a class type,
a template parameter object ([[temp.param]](temp.param "13.2 Template parameters")) exists
that is constructed so as to be template-argument-equivalent to v;P denotes that template parameter object[.](#4.sentence-1)

P is copy-initialized from an unspecified candidate initializer
that is template-argument-equivalent to v[.](#4.sentence-2)

If, for the initialization from any candidate initializer,

- [(4.1)](#4.1)

the initialization would be ill-formed, or

- [(4.2)](#4.2)

the full-expression of an invented [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]") for the initialization would not be a constant expression
when interpreted as a [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ([[expr.const]](expr.const "7.7 Constant expressions")), or

- [(4.3)](#4.3)

the initialization would cause P to not be template-argument-equivalent ([[temp.type]](temp.type "13.6 Type equivalence")) to v,

the program is ill-formed[.](#4.sentence-3)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1294)

Otherwise, the value of P is that of v[.](#5.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1297)

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):

- [(6.1)](#6.1)

a temporary object ([[class.temporary]](class.temporary "6.8.7 Temporary objects")),

- [(6.2)](#6.2)

a string literal object ([[lex.string]](lex.string "5.13.5 String literals")),

- [(6.3)](#6.3)

the result of a typeid expression ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),

- [(6.4)](#6.4)

a predefined __func__ variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")), or

- [(6.5)](#6.5)

a subobject ([[intro.object]](intro.object "6.8.2 Object model")) of one of the above[.](#6.sentence-1)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1311)

[*Example [1](#example-1)*: template <int& r> class A{};extern int x;
A<x> a; // OKvoid f(int p) {constexpr int& r = p; // OK A<r> a; // error: a static constexpr int& variable cannot be initialized to refer to p here} â *end example*]

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1324)

[*Example [2](#example-2)*: template<const int* 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*]

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1370)

[*Note [2](#note-2)*:

A [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") ([[lex.string]](lex.string "5.13.5 String literals")) is
not an acceptable [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") for a constant template parameter of non-class type[.](#9.sentence-1)

[*Example [3](#example-3)*: template<class T, T p> class X {/* ... */};

X<const char*, "Studebaker"> x; // error: string literal object as [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") X<const char*, "Knope" + 1> x2; // error: subobject of string literal object as [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")const char p[] = "Vivisectionist";
X<const char*, p> y; // OKstruct A {constexpr A(const char*) {}};

X<A, "Pyrophoricity"> z; // OK, [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") is a constructor argument to A â *end example*]

â *end note*]

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1396)

[*Note [3](#note-3)*:

A temporary object
is not an acceptable[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") when the corresponding
template parameter
has reference type[.](#10.sentence-1)

[*Example [4](#example-4)*: template<const int& 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 { const int &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*]

â *end note*]
