[temp.variadic]

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

## 13.7 Template declarations [[temp.decls]](temp.decls#temp.variadic)

### 13.7.4 Variadic templates [temp.variadic]

[1](#1)

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

A [*template parameter pack*](#def:template_parameter_pack "13.7.4 Variadic templates [temp.variadic]") is a template parameter
that accepts zero or more template arguments[.](#1.sentence-1)

[*Example [1](#example-1)*: template<class ... Types> struct Tuple { };

Tuple<> t0; // Types contains no arguments Tuple<int> t1; // Types contains one argument: int Tuple<int, float> t2; // Types contains two arguments: int and float Tuple<0> error; // error: 0 is not a type â *end example*]

[2](#2)

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

A [*function parameter pack*](#def:function_parameter_pack "13.7.4 Variadic templates [temp.variadic]") is a function parameter
that accepts zero or more function arguments[.](#2.sentence-1)

[*Example [2](#example-2)*: template<class ... Types> void f(Types ... args);

f(); // args contains no arguments f(1); // args contains one argument: int f(2, 1.0); // args contains two arguments: int and double â *end example*]

[3](#3)

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

An [](#def:init-capture_pack "13.7.4 Variadic templates [temp.variadic]")*[*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") pack* is a lambda capture that introduces an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") for each of the elements in the pack expansion of its [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")[.](#3.sentence-1)

[*Example [3](#example-3)*: template <typename... Args>void foo(Args... args) {[...xs=args]{ bar(xs...); // xs is an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") pack};} foo(); // xs contains zero [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]")*s* foo(1); // xs contains one [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") â *end example*]

[4](#4)

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

A [*structured binding pack*](#def:structured_binding_pack "13.7.4 Variadic templates [temp.variadic]") is an [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1 Preamble [dcl.pre]") that introduces zero or more structured bindings ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations"))[.](#4.sentence-1)

[*Example [4](#example-4)*: auto foo() -> int(&)[2];

template <class T>void g() {auto [...a] = foo(); // a is a structured binding pack containing two elementsauto [b, c, ...d] = foo(); // d is a structured binding pack containing zero elements} â *end example*]

[5](#5)

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

A [*pack*](#def:pack "13.7.4 Variadic templates [temp.variadic]") is
a template parameter pack,
a function parameter pack,
an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") pack, or
a structured binding pack[.](#5.sentence-1)

The number of elements of a template parameter pack
or a function parameter pack
is the number of arguments provided for the parameter pack[.](#5.sentence-2)

The number of elements of an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") pack
is the number of elements in the pack expansion of its [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")[.](#5.sentence-3)

[6](#6)

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

A [*pack expansion*](#def:pack_expansion "13.7.4 Variadic templates [temp.variadic]") consists of a [*pattern*](#def:pack_expansion,pattern "13.7.4 Variadic templates [temp.variadic]") and an ellipsis, the instantiation of which
produces zero or more instantiations of the pattern in a list (described below)[.](#6.sentence-1)

The form of the pattern
depends on the context in which the expansion occurs[.](#6.sentence-2)

Pack
expansions can occur in the following contexts:

- [(6.1)](#6.1)

  In a function parameter pack ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")); the pattern is the[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") without the ellipsis[.](#6.1.sentence-1)

- [(6.2)](#6.2)

  In a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"));
the pattern is a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]")[.](#6.2.sentence-1)

- [(6.3)](#6.3)

  In a [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1 General [class.mem.general]") ([[class.mem.general]](class.mem.general "11.4.1 General"));
the pattern is a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [class.mem.general]")[.](#6.3.sentence-1)

- [(6.4)](#6.4)

  In a template parameter pack that is a pack expansion ([[temp.param]](temp.param "13.2 Template parameters")):
  * [(6.4.1)](#6.4.1)

if the template parameter pack is a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]");
the pattern is the [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") without the ellipsis;

  * [(6.4.2)](#6.4.2)

if the template parameter pack is a [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]");
the pattern is the corresponding [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") without the ellipsis;

  * [(6.4.3)](#6.4.3)

if the template parameter pack is a template template parameter;
the pattern is the corresponding[*type-tt-parameter*](temp.param#nt:type-tt-parameter "13.2 Template parameters [temp.param]"),[*variable-tt-parameter*](temp.param#nt:variable-tt-parameter "13.2 Template parameters [temp.param]"), or[*concept-tt-parameter*](temp.param#nt:concept-tt-parameter "13.2 Template parameters [temp.param]") without the ellipsis[.](#6.4.sentence-1)

- [(6.5)](#6.5)

  In an [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") ([[dcl.init]](dcl.init "9.5 Initializers"));
the pattern is an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")[.](#6.5.sentence-1)

- [(6.6)](#6.6)

  In a [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1 General [class.derived.general]") ([[class.derived]](class.derived "11.7 Derived classes"));
the pattern is a [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1 General [class.derived.general]")[.](#6.6.sentence-1)

- [(6.7)](#6.7)

  In a [*mem-initializer-list*](class.base.init#nt:mem-initializer-list "11.9.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")) for a[*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") whose [*mem-initializer-id*](class.base.init#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]") denotes a
base class; the pattern is the [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]")[.](#6.7.sentence-1)

- [(6.8)](#6.8)

  In a [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]") ([[temp.arg]](temp.arg "13.4 Template arguments"));
the pattern is a [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")[.](#6.8.sentence-1)

- [(6.9)](#6.9)

  In an [*attribute-list*](dcl.attr.grammar#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics"));
the pattern is an [*attribute*](dcl.attr.grammar#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#6.9.sentence-1)

- [(6.10)](#6.10)

  In an [*annotation-list*](dcl.attr.grammar#nt:annotation-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics"));
the pattern is an [*annotation*](dcl.attr.grammar#nt:annotation "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#6.10.sentence-1)

- [(6.11)](#6.11)

  In an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.align]](dcl.align "9.13.2 Alignment specifier")); the pattern is
the [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") without the ellipsis[.](#6.11.sentence-1)

- [(6.12)](#6.12)

  In a [*capture-list*](expr.prim.lambda.capture#nt:capture-list "7.5.6.3 Captures [expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3 Captures")); the pattern is
the [*capture*](expr.prim.lambda.capture#nt:capture "7.5.6.3 Captures [expr.prim.lambda.capture]") without the ellipsis[.](#6.12.sentence-1)

- [(6.13)](#6.13)

  In a [sizeof... expression](expr.sizeof "7.6.2.5 Sizeof [expr.sizeof]"); the pattern is an[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")[.](#6.13.sentence-1)

- [(6.14)](#6.14)

  In a [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4 Pack indexing expression [expr.prim.pack.index]");
the pattern is an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")[.](#6.14.sentence-1)

- [(6.15)](#6.15)

  In a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]");
the pattern is a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")[.](#6.15.sentence-1)

- [(6.16)](#6.16)

  In a [*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7 Fold expressions [expr.prim.fold]") ([[expr.prim.fold]](expr.prim.fold "7.5.7 Fold expressions"));
the pattern is the [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") that contains an unexpanded pack[.](#6.16.sentence-1)

- [(6.17)](#6.17)

  In a fold expanded constraint ([[temp.constr.fold]](temp.constr.fold "13.5.2.5 Fold expanded constraint"));
the pattern is the constraint of that fold expanded constraint[.](#6.17.sentence-1)

[*Example [5](#example-5)*: template<class ... Types> void f(Types ... rest);template<class ... Types> void g(Types ... rest) { f(&rest ...); // â&rest ...'' is a pack expansion; â&rest'' is its pattern} â *end example*]

[7](#7)

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

For the purpose of determining whether a pack satisfies a rule
regarding entities other than packs, the pack is
considered to be the entity that would result from an instantiation of
the pattern in which it appears[.](#7.sentence-1)

[8](#8)

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

A pack whose name appears within the pattern of a pack
expansion is expanded by that pack expansion[.](#8.sentence-1)

An appearance of the name of
a pack is only expanded by the innermost enclosing pack expansion[.](#8.sentence-2)

The pattern of a pack expansion shall name one or more packs that
are not expanded by a nested pack expansion; such packs are called[*unexpanded packs*](#def:pack,unexpanded "13.7.4 Variadic templates [temp.variadic]") in the pattern[.](#8.sentence-3)

All of the packs expanded
by a pack expansion shall have the same number of arguments specified[.](#8.sentence-4)

An
appearance of a name of a pack that is not expanded is
ill-formed[.](#8.sentence-5)

[*Example [6](#example-6)*: template<typename...> struct Tuple {};template<typename T1, typename T2> struct Pair {};

template<class ... Args1> struct zip {template<class ... Args2> struct with {typedef Tuple<Pair<Args1, Args2> ... > type; };};

typedef zip<short, int>::with<unsigned short, unsigned>::type T1; // T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>>typedef zip<short>::with<unsigned short, unsigned>::type T2; // error: different number of arguments specified for Args1 and Args2template<class ... Args>void g(Args ... args) { // OK, Args is expanded by the function parameter pack args f(const_cast<const Args*>(&args)...); // OK, âArgs'' and âargs'' are expanded f(5 ...); // error: pattern does not contain any packs f(args); // error: pack âargs'' is not expanded f(h(args ...) + args ...); // OK, first âargs'' expanded within h,// second âargs'' expanded within f} â *end example*]

[9](#9)

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

The instantiation of a pack expansion considers
items E1,E2,â¦,EN,
whereN is the number of elements in the pack expansion parameters[.](#9.sentence-1)

Each Ei is generated by instantiating the pattern and
replacing each pack expansion parameter with its ith element[.](#9.sentence-2)

Such an element, in the context of the instantiation, is interpreted as
follows:

- [(9.1)](#9.1)

if the pack is a template parameter pack, the element is
  * [(9.1.1)](#9.1.1)

a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") for a type template parameter pack,

  * [(9.1.2)](#9.1.2)

an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") for a constant template parameter pack, or

  * [(9.1.3)](#9.1.3)

a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") for a template template parameter pack

designating the ith corresponding
type, constant, or template template argument;

- [(9.2)](#9.2)

if the pack is a function parameter pack, the element is an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") designating the ith function parameter
that resulted from instantiation of
the function parameter pack declaration;

- [(9.3)](#9.3)

if the pack is an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") pack,
the element is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") designating the variable introduced by
the ith [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") that resulted from instantiation of
the [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") pack declaration;
otherwise

- [(9.4)](#9.4)

if the pack is a structured binding pack,
the element is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") designating the ith structured binding in the pack
that resulted from the structured binding declaration.

When N is zero, the instantiation of a pack expansion
does not alter the syntactic interpretation of the enclosing construct,
even in cases where omitting the pack expansion entirely would
otherwise be ill-formed or would result in an ambiguity in the grammar[.](#9.sentence-4)

[10](#10)

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

The instantiation of a sizeof... expression ([[expr.sizeof]](expr.sizeof "7.6.2.5 Sizeof")) produces
an integral constant with value N[.](#10.sentence-1)

[11](#11)

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

When instantiating a [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4 Pack indexing expression [expr.prim.pack.index]") P,
let K be the index of P[.](#11.sentence-1)

The instantiation of P is the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") EK[.](#11.sentence-2)

[12](#12)

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

When instantiating a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]") P,
let K be the index of P[.](#12.sentence-1)

The instantiation of P is the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") EK[.](#12.sentence-2)

[13](#13)

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

The instantiation of an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") with an ellipsis
produces E1 E2 … EN[.](#13.sentence-1)

[14](#14)

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

The instantiation of a [*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7 Fold expressions [expr.prim.fold]") ([[expr.prim.fold]](expr.prim.fold "7.5.7 Fold expressions")) produces:

- [(14.1)](#14.1)

( ((E1*op* E2)*op* â¯)*op* EN) for a unary left fold,

- [(14.2)](#14.2)

( E1 *op*(â¯ *op*(ENâ1 *op*EN))) for a unary right fold,

- [(14.3)](#14.3)

( (((E*op* E1)*op* E2)*op* â¯)*op* EN) for a binary left fold, and

- [(14.4)](#14.4)

( E1 *op*(â¯ *op*(ENâ1 *op*(EN *op*E)))) for a binary right fold[.](#14.sentence-1)

In each case,*op* is the [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]")[.](#14.sentence-2)

For a binary fold,E is generated
by instantiating the [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") that did not contain an unexpanded pack[.](#14.sentence-3)

[*Example [7](#example-7)*: template<typename ...Args>bool all(Args ...args) { return (... && args); }bool b = all(true, true, true, false);

Within the instantiation of all,
the returned expression expands to((true && true) && true) && false,
which evaluates to false[.](#14.sentence-4)

â *end example*]

If N is zero for a unary fold,
the value of the expression is shown in Table [20](#tab:temp.fold.empty "Table 20: Value of folding empty sequences");
if the operator is not listed in Table [20](#tab:temp.fold.empty "Table 20: Value of folding empty sequences"),
the instantiation is ill-formed[.](#14.sentence-5)

Table [20](#tab:temp.fold.empty) — Value of folding empty sequences [[tab:temp.fold.empty]](./tab:temp.fold.empty)  

| [ð](#tab:temp.fold.empty-row-1)<br>**Operator** | **Value when pack is empty** |
| --- | --- |
| [ð](#tab:temp.fold.empty-row-2)<br>&& | true |
| [ð](#tab:temp.fold.empty-row-3)<br>|| | false |
| [ð](#tab:temp.fold.empty-row-4)<br>, | void() |

[15](#15)

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

A fold expanded constraint is not instantiated ([[temp.constr.fold]](temp.constr.fold "13.5.2.5 Fold expanded constraint"))[.](#15.sentence-1)

[16](#16)

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

The instantiation of any other pack expansion
produces a list of elements E1,E2,â¦,EN[.](#16.sentence-1)

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

The variety of list varies with the context:[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]"),[*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1 General [class.derived.general]"),[*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]"), etc[.](#16.sentence-2)

â *end note*]

When N is zero, the instantiation of the expansion produces an empty list[.](#16.sentence-3)

[*Example [8](#example-8)*: template<class... T> struct X : T... { };template<class... T> void f(T... values) { X<T...> x(values...);}template void f<>(); // OK, X<> has no base classes// x is a variable of type X<> that is value-initialized â *end example*]
