13 Templates [temp]

13.4 Template arguments [temp.arg]

13.4.1 General [temp.arg.general]

There are three forms of template-argument, corresponding to the three forms of template-parameter: type, non-type and template.
The type and form of each template-argument specified in a template-id shall match the type and form specified for the corresponding parameter declared by the template in its template-parameter-list.
When the parameter declared by the template is a template parameter pack, it will correspond to zero or more template-arguments.
[Example 1: template<class T> class Array { T* v; int sz; public: explicit Array(int); T& operator[](int); T& elem(int i) { return v[i]; } }; Array<int> v1(20); typedef std::complex<double> dcomplex; // std​::​complex is a standard library template Array<dcomplex> v2(30); Array<dcomplex> v3(40); void bar() { v1[3] = 7; v2[3] = v3.elem(4) = dcomplex(7,8); } — end example]
The template argument list of a template-head is a template argument list in which the template argument has the value of the template parameter of the template-head.
If the template parameter is a template parameter pack ([temp.variadic]), the template argument is a pack expansion whose pattern is the name of the template parameter pack.
In a template-argument, an ambiguity between a type-id and an expression is resolved to a type-id, regardless of the form of the corresponding template-parameter.112
[Example 2: template<class T> void f(); template<int I> void f(); void g() { f<int()>(); // int() is a type-id: call the first f() } — end example]
[Note 1: 
Names used in a template-argument are subject to access control where they appear.
Because a template-parameter is not a class member, no access control applies.
— end note]
[Example 3: template<class T> class X { static T t; }; class Y { private: struct S { /* ... */ }; X<S> x; // OK, S is accessible // X<Y​::​S> has a static member of type Y​::​S // OK, even though Y​::​S is private }; X<Y::S> y; // error: S not accessible — end example]
For a template argument that is a class type or a class template, the template definition has no special access rights to the members of the template argument.
[Example 4: template <template <class TT> class T> class A { typename T<int>::S s; }; template <class U> class B { private: struct S { /* ... */ }; }; A<B> b; // error: A has no access to B​::​S — end example]
When template argument packs or default template arguments are used, a template-argument list can be empty.
In that case the empty <> brackets shall still be used as the template-argument-list.
[Example 5: template<class T = char> class String; String<>* p; // OK, String<char> String* q; // syntax error template<class ... Elements> class Tuple; Tuple<>* t; // OK, Elements is empty Tuple* u; // syntax error — end example]
An explicit destructor call ([class.dtor]) for an object that has a type that is a class template specialization may explicitly specify the template-arguments.
[Example 6: template<class T> struct A { ~A(); }; void f(A<int>* p, A<int>* q) { p->A<int>::~A(); // OK, destructor call q->A<int>::~A<int>(); // OK, destructor call } — end example]
If the use of a template argument gives rise to an ill-formed construct in the instantiation of a template specialization, the program is ill-formed.
When name lookup for the component name of a template-id finds an overload set, both non-template functions in the overload set and function templates in the overload set for which the template-arguments do not match the template-parameters are ignored.
[Note 2: 
If none of the function templates have matching template-parameters, the program is ill-formed.
— end note]
When a simple-template-id does not name a function, a default template-argument is implicitly instantiated when the value of that default argument is needed.
[Example 7: template<typename T, typename U = int> struct S { }; S<bool>* p; // the type of p is S<bool, int>*
The default argument for U is instantiated to form the type S<bool, int>*.
— end example]
A template-argument followed by an ellipsis is a pack expansion.
112)112)
There is no such ambiguity in a default template-argument because the form of the template-parameter determines the allowable forms of the template-argument.

13.4.2 Template type arguments [temp.arg.type]

A template-argument for a template-parameter which is a type shall be a type-id.
[Example 1: template <class T> class X { }; template <class T> void f(T t) { } struct { } unnamed_obj; void f() { struct A { }; enum { e1 }; typedef struct { } B; B b; X<A> x1; // OK X<A*> x2; // OK X<B> x3; // OK f(e1); // OK f(unnamed_obj); // OK f(b); // OK } — end example]
[Note 1: 
A template type argument can be an incomplete type ([basic.types.general]).
— end note]

13.4.3 Template non-type arguments [temp.arg.nontype]

If the type T of a template-parameter ([temp.param]) 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 the type deduced for the variable x in the invented declaration T x = E ; where E is the template argument provided for the parameter.
[Note 1: 
E is a template-argument or (for a default template argument) an initializer-clause.
— end note]
If a deduced parameter type is not permitted for a template-parameter declaration ([temp.param]), the program is ill-formed.
The value of a non-type template-parameter P 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).
Otherwise, a temporary variable constexpr T v = A; is introduced.
The lifetime of v ends immediately after initializing it and any template parameter object (see below).
For each such variable, the id-expression v is termed a candidate initializer.
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 program is ill-formed.
Otherwise, the value of P is that of v.
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<const int* pci> struct X { /* ... */ }; int ai[10]; X<ai> xi; // array to pointer and qualification conversions struct Y { /* ... */ }; template<const Y& b> struct Z { /* ... */ }; Y y; Z<y> z; // no conversion, but note extra cv-qualification template<int (&pa)[5]> struct W { /* ... */ }; int b[5]; W<b> w; // no conversion void 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 void template<int i> struct C { /* ... */ }; C<{ 42 }> c1; // OK struct J1 { J1 *self = this; }; B<J1{}> j1; // error: initialization of template parameter object is not a constant expression struct 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]
[Note 2: 
A string-literal ([lex.string]) is not an acceptable template-argument for a template-parameter of non-class type.
[Example 2: template<class T, T p> class X { /* ... */ }; X<const char*, "Studebaker"> x; // error: string literal object as template-argument X<const char*, "Knope" + 1> x2; // error: subobject of string literal object as template-argument const char p[] = "Vivisectionist"; X<const char*, p> y; // OK struct A { constexpr A(const char*) {} }; X<A, "Pyrophoricity"> z; // OK, string-literal is a constructor argument to A — end example]
— end note]
[Note 3: 
A temporary object is not an acceptable template-argument when the corresponding template-parameter has reference type.
[Example 3: template<const int& CRI> struct B { /* ... */ }; B<1> b1; // error: temporary would be required for template argument int c = 1; B<c> b2; // OK struct 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]

13.4.4 Template template arguments [temp.arg.template]

A template-argument for a template template-parameter shall be the name of a class template or an alias template, expressed as id-expression.
Only primary templates are considered when matching the template template argument with the corresponding parameter; partial specializations are not considered even if their parameter lists match that of the template template parameter.
Any partial specializations ([temp.spec.partial]) associated with the primary template are considered when a specialization based on the template template-parameter is instantiated.
If a specialization is not reachable from the point of instantiation, and it would have been selected had it been reachable, the program is ill-formed, no diagnostic required.
[Example 1: template<class T> class A { // primary template int x; }; template<class T> class A<T*> { // partial specialization long x; }; template<template<class U> class V> class C { V<int> y; V<int*> z; }; C<A> c; // V<int> within C<A> uses the primary template, so c.y.x has type int // V<int*> within C<A> uses the partial specialization, so c.z.x has type long — end example]
A template-argument matches a template template-parameter P when P is at least as specialized as the template-argument A.
In this comparison, if P is unconstrained, the constraints on A are not considered.
If P contains a template parameter pack, then A also matches P if each of A's template parameters matches the corresponding template parameter in the template-head of P.
Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are equivalent ([temp.over.link]), and for template template-parameters, each of their corresponding template-parameters matches, recursively.
When P's template-head contains a template parameter pack ([temp.variadic]), the template parameter pack will match zero or more template parameters or template parameter packs in the template-head of A with the same type and form as the template parameter pack in P (ignoring whether those template parameters are template parameter packs).
[Example 2: template<class T> class A { /* ... */ }; template<class T, class U = T> class B { /* ... */ }; template<class ... Types> class C { /* ... */ }; template<auto n> class D { /* ... */ }; template<template<class> class P> class X { /* ... */ }; template<template<class ...> class Q> class Y { /* ... */ }; template<template<int> class R> class Z { /* ... */ }; X<A> xa; // OK X<B> xb; // OK X<C> xc; // OK Y<A> ya; // OK Y<B> yb; // OK Y<C> yc; // OK Z<D> zd; // OK — end example]
[Example 3: template <class T> struct eval; template <template <class, class...> class TT, class T1, class... Rest> struct eval<TT<T1, Rest...>> { }; template <class T1> struct A; template <class T1, class T2> struct B; template <int N> struct C; template <class T1, int N> struct D; template <class T1, class T2, int N = 17> struct E; eval<A<int>> eA; // OK, matches partial specialization of eval eval<B<int, float>> eB; // OK, matches partial specialization of eval eval<C<17>> eC; // error: C does not match TT in partial specialization eval<D<int, 17>> eD; // error: D does not match TT in partial specialization eval<E<int, float>> eE; // error: E does not match TT in partial specialization — end example]
[Example 4: template<typename T> concept C = requires (T t) { t.f(); }; template<typename T> concept D = C<T> && requires (T t) { t.g(); }; template<template<C> class P> struct S { }; template<C> struct X { }; template<D> struct Y { }; template<typename T> struct Z { }; S<X> s1; // OK, X and P have equivalent constraints S<Y> s2; // error: P is not at least as specialized as Y S<Z> s3; // OK, P is at least as specialized as Z — end example]
A template template-parameter P is at least as specialized as a template template-argument A if, given the following rewrite to two function templates, the function template corresponding to P is at least as specialized as the function template corresponding to A according to the partial ordering rules for function templates.
Given an invented class template X with the template-head of A (including default arguments and requires-clause, if any):
  • Each of the two function templates has the same template parameters and requires-clause (if any), respectively, as P or A.
  • Each function template has a single function parameter whose type is a specialization of X with template arguments corresponding to the template parameters from the respective function template where, for each template parameter PP in the template-head of the function template, a corresponding template argument AA is formed.
    If PP declares a template parameter pack, then AA is the pack expansion PP... ([temp.variadic]); otherwise, AA is the id-expression PP.
If the rewrite produces an invalid type, then P is not at least as specialized as A.