[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 struct Tuple { }; Tuple<> t0; // Types contains no arguments Tuple t1; // Types contains one argument: int Tuple 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 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 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 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 void f(Types ... rest);template 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 struct Tuple {};template struct Pair {}; template struct zip {template struct with {typedef Tuple ... > type; };}; typedef zip::with::type T1; // T1 is Tuple, Pair>typedef zip::with::type T2; // error: different number of arguments specified for Args1 and Args2templatevoid g(Args ... args) { // OK, Args is expanded by the function parameter pack args f(const_cast(&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)*: templatebool 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)
**Operator** | **Value when pack is empty** | | --- | --- | | [🔗](#tab:temp.fold.empty-row-2)
&& | true | | [🔗](#tab:temp.fold.empty-row-3)
|| | false | | [🔗](#tab:temp.fold.empty-row-4)
, | 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 struct X : T... { };template void f(T... values) { X x(values...);}template void f<>(); // OK, X<> has no base classes// x is a variable of type X<> that is value-initialized — *end example*]