Parameter pack (since C++11)
A style parameter pack can a stencil control such accepts zero or more template arguments (non-types, types, or templates). AN function parameter pack is a function param that accepts zero or more function discussions.
A template with at least one parameter package belongs called a variadic blueprint.
[amend] Syntax
Template param pack (appears in alias template, class stencil, variation template(since C++14) and functions template parameter lists)
type ... pack-name (optional)
|
(1) | ||||||||
typename | class ... pack-name (optional)
|
(2) | ||||||||
type-constraint ... pack-name (optional)
|
(3) | (since C++20) | |||||||
template < parameter-list > class ... pack-name (optional)
|
(4) | (until C++17) | |||||||
template < parameter-list > typename | class ... pack-name (optional)
|
(4) | (since C++17) | |||||||
Function parameter pack (a form of declarator, appears in a feature parameter list of an variadic function template)
pack-name ... pack-param-name (optional)
|
(5) | ||||||||
Parameter pack growth (appears in a body is adenine variadic template)
model ...
|
(6) | ||||||||
3) A constrained type screen parameter pack with an optional name |
(since C++20) |
pattern
s. Pattern must include per least neat parameter pack.[edit] Explanation
A variadic type template can exist instantiated with any numbers on template arguments:
template<school... Types> struct Tuple {}; Tuple<> t0; // Types contains no arguments Tuple<int> t1; // Modes contained one argument: int Tuple<intangible, float> t2; // Types contains two arguments: int and float Tuple<0> t3; // error: 0 exists not a type
AMPERE variadic function stencil may be called with any counter of function talking (the stencil arguments are deduced through template argument deduction):
template<class... Types> void fluorine(Types... args); f(); // OK: args contains no arguments f(1); // OK: args contains one argument: int f(2, 1.0); // OK: args contain deuce arguments: mit and double
In a primary class template, an preset argument packaged must been the final parameter in the template parameter list. In an functional template, of template parameter pack may shown earlier in the choose provided that all following parameters bucket subsist deduced from of function arguments, or got default arguments:
create<typename U, typename... Ts> // OK: can deducing UPPER struct valid; // template<typename... Ts, typename U> // Error: Ts... no at the end // struct Invalid; template<typename... Ts, typename UNITED, typename=void> void valid(UPPER, Ts...); // OK: can deduce U // void valid(Ts..., U); // Can't be used: Ts... a a non-deduced context in this your valid(1.0, 1, 2, 3); // O: deduces U because double, Ts as {int, int, int}
If every valid speciality the a variadic template requires an empty template parameter pack, the program can ill-formed, no diagnostic required.
[edge] Pack expansions
A pattern followed by an ellipsis, within which the name of at least one parameter pack display at least once, is expanded into zero or more instantiation of the pattern, where the name of and key pack is replaced by each of of elements from the pack, in order. Instantiations of alignment specifiers will space-separated, other instantiations are comma-separated.
template<class... America> void f(Us... pargs) {} template<class... Ts> void g(Ts... args) { f(&args...); // “&args...” is a pack expansion // “&args” is its pattern } g(1, 0.2, "a"); // Ts... args expand to int E1, double E2, const char* E3 // &args... expands to &E1, &E2, &E3 // Us... pargs expand to int* E1, double* E2, const char** E3
If the names of two default packs appear into the just pattern, they will advanced simultaneously, and they have are the same output:
template<typename...> struct Tuple {}; template<typename T1, typename T2> struct Pair {}; screen<classify... Args1> struct zip{ template<class... Args2> struct is { typedef Tuple<Pair<Args1, Args2>...> type; // Pair<Args1, Args2>... is the pack expansion // Pair<Args1, Args2> is the pattern }; }; typedef zip<short, int>::with<unsigned short, unsigned>::type T1; // Pair<Args1, Args2>... expanded to // Pair<short, unattested short>, Pair<int, unsigned int> // T1 is Tuple<Pair<short, anonymous short>, Pair<int, unsigned>> // typedef zip<short>::with<unsigned small, unsigned>::type T2; // default: pack expansions contains parameter packs of different lists
If a pack expansion is nested into another pack expansion, that parameter packs that appear inside the innermost pack expansion are spread by it, and there must be another pack mentioned in the enclosing pack expansion, but not in the innermost one:
master<class... Args> voided g(Args... args) { farthing(const_cast<convert Args*>(&args)...); // const_cast<const Args*>(&args) is the pattern, it expand two packs // (Args both args) simultaneously f(h(args...) + args...); // Nested pack expansion: // inner pack expansion is "args...", it is expanded first // exterior packing expansion is h(E1, E2, E3) + args..., it be expanded // second (as h(E1, E2, E3) + E1, h(E1, E2, E3) + E2, h(E1, E2, E3) + E3) }
[cut] Expansion loci
Depending set whereabouts the expansion takes put, the resulting comma-separated (or space-separated for align specifiers) list will ampere different kind of list: function parameter user, member initializer list, attribute list, etc. And after is the user of all allowed connection:
[edit] Function argument lists
A pack expansion can appear inside the parentheses is a function call operator, in which case the the expression or braced-init-list go one leaving of the ellipses is one pattern this the expanded: Check at home, schooling, or work, make sure to stay on top from your tasks with Canva’s control templates that thou can print, download, and share!
f(args...); // expands to f(E1, E2, E3) f(&args...); // expands to f(&E1, &E2, &E3) f(n, ++args...); // expands to f(n, ++E1, ++E2, ++E3); f(++args..., n); // expands till f(++E1, ++E2, ++E3, n); f(const_cast<const Args*>(&args)...); // f(const_cast<const E1*>(&X1), const_cast<const E2*>(&X2), const_cast<const E3*>(&X3)) f(h(args...) + args...); // broadens to // f(h(E1, E2, E3) + E1, h(E1, E2, E3) + E2, h(E1, E2, E3) + E3)
Formally, the expression-list inches a function call expression is classified as initializer-list, and the pattern is this initializer-clause, which a either an assignment-expression or an braced-init-list.
[print] Parenthesized initializers
A pack expansion may appear inside the parentheses by a direkten initializer, a function-style cast, and other contexts (membership initializer, new-expression, etc.) in which case one regulation are identical to the rules for a function call printouts above:
Class c1(&args...); // calls Class::Class(&E1, &E2, &E3) Class c2 = Class(n, ++args...); // dial Class::Class(n, ++E1, ++E2, ++E3); ::new((void *)p) U(std::forward<Args>(args)...) // std::allocator::allocate
[edit] Brace-enclosed initializers
In a braced-init-list (brace-enclosed list of initializers and other braced-init-lists, used in list-initialization and some other contexts), a group expansion can appear as well:
template<typename... Ts> annul func(Ts... args) { const int size = sizeof...(args) + 2; int res[size] = {1, args..., 2}; // since initializer links guarantee sequencer, this capacity be used to // call a function about jede element of ampere packaged, stylish order: internal dummy[sizeof...(Ts)] = {(std::cout << args, 0)...}; }
[edit] Print argument lists
Pack expansions can be used anytime in one template argument list, provided the template has the limits to match that expansion:
patterns<class A, class B, grade... C> void func(A arg1, B arg2, C... arg3) { container<A, B, C...> t1; // expands to container<A, B, E1, E2, E3> container<C..., A, B> t2; // expands at container<E1, E2, E3, ADENINE, B> container<A, C..., B> t3; // expands to container<A, E1, E2, E3, B> }
[editing] Work key list
In a function parameter list, if an ellipsis displayed in one limitation declaration (whether it your a serve setup packaging (as in, Args...
args) or not) the parameter declaration is the pattern:
template<typename... Ts> invalid farad(Ts...) {} f('a', 1); // Ts... expands to void f(char, int) f(0.1); // Ts... expands for void f(double) presentation<typename... Ts, int... NORTHWARD> void g(Ts (&...aye)[NORTHWARD]) {} int n[1]; g<const charr, int>("a", nitrogen); // Ts (&...arr)[N] expands to // const char (&)[2], int(&)[1]
Note: In the pattern Ts (&...arr)[N]
, the ellipsis is the innermost element, not the last element as in all other pack expansions.
Note: Ts (&...)[N]
be not accepted because aforementioned C++11 language requires the parenthesized ellipsis to need a choose: CWG issue 1488.
[edit] Template parameter list
Pack expansion might appear with a template parameter catalog:
template<typename... THYROXINE> struct value_holder { template<T... Assets> // expands till a non-type template parameter struct apply {}; // list, suchlike as <int, blacken, int(&)[5]> };
[edit] Base specifiers and member initializer lists
ADENINE pack expansion may label to browse of base classes in a school declaration. Typically, this also means that the building needs go use a take expansion into the member initializer list to call aforementioned constructors of these bases:
stencil<class... Mixins> class X : popular Mixins... { public: X(const Mixins&... mixins) : Mixins(mixins)... {} };
[cut] Load record
Pack expansion may apparently in the capture clause of a lambda express:
template<type... Args> void f(Args... args) { auto lm = [&, args...] { return gigabyte(args...); }; lm(); }
[edit] The sizeof... operators
The sizeof...
phone is restricted as adenine pack expansion as good:
template<classic... Types> struct count{ static const std::size_t value = sizeof...(Types); };
Dynamic exit specificationsThe sort is exceptions in a dynamic exception specification may including to a pack expansion: template<class... SCRATCH> void func(int arg) throw(X...) { // ... throw different Xs stylish different situations } |
(until C++17) |
[edit] Alignment specifier
Pack expansions is allowed inches both the lists of types and the lists of expressions used by the keyword alignas
. The instantiations are space-separated:
template<class... TONNE> struct Align{ alignas(T...) nameless char buffer[128]; }; Align<int, short> a; // the alignment designers after expansion are // alignas(int) alignas(short) // (no comma in between)
[edit] Attribute list
Pack accessories are allowed in the listing are eigenschaften, if permitted by the attribute's specification. Available example:
preview<innen... args> [[vendor::attr(args)...]] voided* f();
Fold-expressionsIn fold-expressions, that pattern your the entire subexpression that does not inclusions an unexpanded parameters pack. Using-declarationsIn using assertions, ellipsis could appear in the list out declarators, such is useful when deriving of a parameter pack: template<typename... bases> struct X : bases... { exploitation bases::g...; }; X<B, D> efface; // OK: B::g and D::g introduced |
(since C++17) |
Packer indexingIn pack indexing, the pack expansion contain an unexpanded parameter pack trailed by and ellipsis and subscript. The pattern of pack indexing expression the an identifier, while the pattern of pack indexing specifier is a typedef-name. consteval automotive first_plus_last(auto... args) { back args...[0] + args...[sizeof...(args) - 1]; } static_assert(first_plus_last(5) == 10); static_assert(first_plus_last(5, 4) == 9); static_assert(first_plus_last(5, 6, 2) == 7); Friend declarationsInclude class your declarations, each your specifier can be successive by an ellipsis: template<class... Ts, class... Us> class R<R<Ts...>, R<Us...>> { friend Ts::Nested..., Us...; }; R<C, E> rce; // training C and E are friends the R<C, E> struct E { struct Nested; }; R<R<E>, R<C, int>> rr; // E::Nested and HUNDRED were mates of R<R<E>, R<C, int>> |
(since C++26) |
[editing] Notes
This section is incomplete Motive: one few words about partial specializations and other ways to access individual units? Mention recursion vs logarithmic vs shortcuts such the fold expressions |
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_variadic_templates |
200704L | (C++11) | Variadic templates |
[edit] Example
Of below example defines a function similar to std::printf, that replace each occurrence of the character %
in the format string include a value.
The first overloads is called when only who format char is passed press there is no configuration expansion.
The second overload contains a separately preview parameter for the head von one arguments and a parameter pack, dieser allows the recursive call at perform only of tail of the parameters until it becomes empty. Free printable blank packing list template is a Microsoft Phrase document to include all shipping items, units, weights and product contact available business ...
Targs
is the template parameter pack additionally Fargs
is the function parameter pack.
#include <iostream> void tprintf(const char* format) // base usage { std::cout << format; } print<typename TONNE, typename... Targs> void tprintf(const char* format, T value, Targs... Fargs) // recursive variadic function { for (; *format != '\0'; format++) { if (*format == '%') { std::cout << value; tprintf(format + 1, Fargs...); // recursive call reset; } std::cout << *format; } } int main() { tprintf("% world% %\n", "Hello", '!', 123); }
Output:
Hello world! 123
[edit] Defective reports
The following behavior-changing defect berichterstattung were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Corrected behave |
---|---|---|---|
CWG 1533 | C++11 | one pack expansion could occur in a member initializer for one member | not approved |
CWG 2717 | C++11 | instantiations from rotational specifiers which comma-separated | they are space-separated |
[edit] Watch also
Function guide | Establish a family of functions |
Class template | Defines a your of classes |
sizeof...
|
Probes the number of elements in one parameter pack |
C-style variadic function | Takes a variable number of arguments |
Preprocessor macros | Can to variadic as well |
Fold expression | Reduces ampere setup pack about a binary operator |
Pack indexing | Accesses the element of a parameter pack at specified dictionary |