[temp.arg.template]

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

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

### 13.4.4 Template template arguments [temp.arg.template]

[1](#1)

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

A[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") for a template
template parameter
shall be the name of a template[.](#1.sentence-1)

For a [*type-tt-parameter*](temp.param#nt:type-tt-parameter "13.2 Template parameters [temp.param]"),
the name shall denote a class template or alias template[.](#1.sentence-2)

For a [*variable-tt-parameter*](temp.param#nt:variable-tt-parameter "13.2 Template parameters [temp.param]"),
the name shall denote a variable template[.](#1.sentence-3)

For a [*concept-tt-parameter*](temp.param#nt:concept-tt-parameter "13.2 Template parameters [temp.param]"),
the name shall denote a concept[.](#1.sentence-4)

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[.](#1.sentence-5)

[2](#2)

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

Any partial specializations ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization")) associated with the
primary template are considered when a
specialization based on the template template parameter is instantiated[.](#2.sentence-1)

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[.](#2.sentence-2)

[*Example [1](#example-1)*: template<class T> class A { // primary templateint x;};template<class T> class A<T*> { // partial specializationlong 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*]

[3](#3)

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

A template template parameter P and
a [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") A are[*compatible*](#def:compatible,template_template_parameter_and_template_argument "13.4.4 Template template arguments [temp.arg.template]") if

- [(3.1)](#3.1)

A denotes a class template or an alias template andP is a type template parameter,

- [(3.2)](#3.2)

A denotes a variable template andP is a variable template parameter, or

- [(3.3)](#3.3)

A denotes a concept andP is a concept template parameter[.](#3.sentence-1)

[4](#4)

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

A template [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") A matches a template
template parameter P whenA and P are compatible andP is at least as specialized as A, ignoring constraints
on A if P is unconstrained[.](#4.sentence-1)

If P contains a template parameter pack, then A also matches P if each of A's template parameters
matches the corresponding template parameter declared in the[*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") of P[.](#4.sentence-2)

Two template parameters match if they are of the same kind,
for constant template parameters, their types are
equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")), and for template template parameters,
each of their corresponding template parameters matches, recursively[.](#4.sentence-3)

When P's [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") contains a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") that declares a template parameter
pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")), the template parameter pack will match zero or more template
parameters or template parameter packs declared in the [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") ofA with the same type and form as the template parameter pack declared in P (ignoring whether those template parameters are template parameter packs)[.](#4.sentence-4)

[*Example [2](#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](#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](#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*]

[5](#5)

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

A template template parameter P is
at least as specialized as a template [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") 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](temp.func.order "13.7.7.3 Partial ordering of function templates [temp.func.order]")[.](#5.sentence-1)

Given an invented class template X with the [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") of A (including default arguments
and [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]"), if any):

- [(5.1)](#5.1)

  Each of the two function templates has the same template parameters
and [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") (if any),
respectively, as P or A[.](#5.1.sentence-1)

- [(5.2)](#5.2)

  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*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") PP in the [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") of the function template,
a corresponding [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") AA is formed[.](#5.2.sentence-1)
  If PP declares a template parameter pack,
then AA is the pack expansion PP... ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"));
otherwise, AA is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") denoting PP[.](#5.2.sentence-2)

If the rewrite produces an invalid type,
then P is not at least as specialized as A[.](#5.sentence-3)
