Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      Pack(since C++11)

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      Jump statements
      Functions
      Function declaration
      Lambda function expression
      inline specifier
      Dynamic exception specifications(until C++17*)
      noexcept specifier(C++11)
      Exceptions
      Namespaces
      Types
      Specifiers
      constexpr(C++11)
      consteval(C++20)
      constinit(C++20)
      Storage duration specifiers
      Initialization
      Expressions
      Alternative representations
      Literals
      Boolean -Integer -Floating-point
      Character -String -nullptr(C++11)
      User-defined(C++11)
      Utilities
      Attributes(C++11)
      Types
      typedef declaration
      Type alias declaration(C++11)
      Casts
      Memory allocation
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Template specialization
      Parameter packs(C++11)
      Miscellaneous
       
      Declarations
       
      Expressions
      General
      Literals
      Operators
      Conversions
       
       

      A pack is a C++ entity that defines one of the following:

      • a parameter pack
      • template parameter pack
      • function parameter pack
      (since C++20)
      (since C++26)

      A template parameter pack is a template parameter that accepts zero or more template arguments (constants, types, or templates). A function parameter pack is a function parameter that accepts zero or more function arguments.

      A lambda init-capture pack is a lambda capture that introduces an init-capture for each of the elements in the pack expansion of its initializer.

      (since C++20)

      A structured binding pack is an identifier in the structured binding declaration that introduces zero or more structured bindings.

      (since C++26)

      The number of elements of a pack is equal to:

      • the number of arguments provided for the parameter pack, if the pack is a template or function parameter pack,
      • the number of elements in the pack expansion of its initializer, if the pack is a lambda init-capture pack,
      (since C++20)
      • structured binding size of the initializer less the number of non-pack elements in the structured binding declaration, if the pack is a structured binding pack.
      (since C++26)

      A template with at least one parameter pack is called avariadic template.

      Contents

      [edit]Syntax

      Template parameter pack (appears inalias template,class template,variable template(since C++14),concept(since C++20) andfunction 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 ofdeclarator, appears in a function parameter list of a variadic function template)

      pack-name...pack-param-name (optional) (5)

      For the syntax of non-parameter packs, seelambda init-capture packandstructured binding pack(since C++26).

      (since C++20)

      Pack expansion (appears in a body of a template)

      pattern... (6)
      1) A constant template parameter pack with an optional name
      2) A type template parameter pack with an optional name
      3) Aconstrained type template parameter pack with an optional name
      (since C++20)
      4) A template template parameter pack with an optional name
      5) A function parameter pack with an optional name
      6) Pack expansion: expands to a list of zero or morepatterns. The pattern must include at least one pack.

      [edit]Explanation

      A variadic class template can be instantiated with any number of template arguments:

      template<class...Types>struct Tuple{}; Tuple<> t0;// Types contains no argumentsTuple<int> t1;// Types contains one argument: intTuple<int,float> t2;// Types contains two arguments: int and floatTuple<0> t3;// error: 0 is not a type

      A variadic function template can be called with any number of function arguments (the template arguments are deduced throughtemplate argument deduction):

      template<class...Types>void f(Types...args); f();// OK: args contains no argumentsf(1);// OK: args contains one argument: intf(2,1.0);// OK: args contains two arguments: int and double

      In a primary class template, the template parameter pack must be the final parameter in the template parameter list. In a function template, the template parameter pack may appear earlier in the list provided that all following parameters can be deduced from the function arguments, or have default arguments:

      template<typename U,typename...Ts>// OK: can deduce Ustruct valid;// template<typename... Ts, typename U> // Error: Ts... not at the end// struct Invalid; template<typename...Ts,typename U,typename=void>void valid(U, Ts...);// OK: can deduce U// void valid(Ts..., U); // Can't be used: Ts... is a non-deduced context in this position valid(1.0,1,2,3);// OK: deduces U as double, Ts as {int, int, int}

      If every valid specialization of a variadic template requires an empty template parameter pack, the program is ill-formed, no diagnostic required.

      [edit]Pack expansion

      A pattern followed by an ellipsis, in which the name of at least one pack appears at least once, isexpanded into zero or more instantiations of the pattern, where the name of the pack is replaced by each of the elements from the pack, in order. Instantiations ofalignment specifiers are space-separated, other instantiations are comma-separated.

      template<class...Us>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 packs appear in the same pattern, they are expanded simultaneously, and they must have the same length:

      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;// Pair<Args1, Args2>... is the pack expansion// Pair<Args1, Args2> is the pattern};}; typedef zip<short,int>::with<unsignedshort,unsigned>::type T1;// Pair<Args1, Args2>... expands to// Pair<short, unsigned short>, Pair<int, unsigned int>// T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>> // typedef zip<short>::with<unsigned short, unsigned>::type T2;// error: pack expansion contains packs of different lengths

      If a pack expansion is nested within another pack expansion, the packs that appear inside the innermost pack expansion are expanded by it, and there must be another pack mentioned in the enclosing pack expansion, but not in the innermost one:

      template<class...Args>void g(Args...args){    f(const_cast<const Args*>(&args)...);// const_cast<const Args*>(&args) is the pattern, it expands two packs// (Args and args) simultaneously     f(h(args...)+ args...);// Nested pack expansion:// inner pack expansion is "args...", it is expanded first// outer pack expansion is h(E1, E2, E3) + args..., it is expanded// second (as h(E1, E2, E3) + E1, h(E1, E2, E3) + E2, h(E1, E2, E3) + E3)}

      When the number of elements in a pack is zero (empty pack), 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 a syntax ambiguity. The instantiation produces an empty list.

      template<class...Bases>struct X: Bases...{}; template<class...Args>void f(Args...args){    X<Args...> x(args...);} templatevoid f<>();// OK, X<> has no base classes// x is a variable of type X<> that is value-initialized

      [edit]Expansion loci

      Depending on where the expansion takes place, the resulting comma-separated (or space-separated foralignment specifiers) list is a different kind of list: function parameter list, member initializer list, attribute list, etc. The following is the list of all allowed contexts:

      [edit]Function argument lists

      A pack expansion may appear inside the parentheses of a function call operator, in which case the largest expression orbrace-enclosed initializer list to the left of the ellipsis is the pattern that is expanded:

      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 to 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...);// expands to// f(h(E1, E2, E3) + E1, h(E1, E2, E3) + E2, h(E1, E2, E3) + E3)

      [edit]Parenthesized initializers

      A pack expansion may appear inside the parentheses of adirect initializer, afunction-style cast, and other contexts (member initializer,new-expression, etc.) in which case the rules are identical to the rules for a function call expression above:

      Class c1(&args...);// calls Class::Class(&E1, &E2, &E3)Class c2= Class(n,++args...);// calls Class::Class(n, ++E1, ++E2, ++E3); ::new((void*)p) U(std::forward<Args>(args)...)// std::allocator::allocate

      [edit]Brace-enclosed initializers

      In a brace-enclosed initializer list, a pack expansion may appear as well:

      template<typename...Ts>void func(Ts...args){constint size= sizeof...(args)+2;int res[size]={1, args...,2}; // since initializer lists guarantee sequencing, this can be used to// call a function on each element of a pack, in order:int dummy[sizeof...(Ts)]={(std::cout<< args,0)...};}

      [edit]Template argument lists

      Pack expansions can be used anywhere in a template argument list, provided the template has the parameters to match the expansion:

      template<class A,class B,class...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 to container<E1, E2, E3, A, B>    container<A, C..., B> t3;// expands to container<A, E1, E2, E3, B>}

      [edit]Function parameter list

      In a function parameter list, if an ellipsis appears in a parameter declaration (whether it names a function parameter pack (as in,Args...args) or not) the parameter declaration is the pattern:

      template<typename...Ts>void f(Ts...){} f('a',1);// Ts... expands to void f(char, int)f(0.1);// Ts... expands to void f(double) template<typename...Ts,int...N>void g(Ts(&...arr)[N]){} int n[1]; g<constchar,int>("a", n);// Ts (&...arr)[N] expands to// const char (&)[2], int(&)[1]

      Note: In the patternTs (&...arr)[N], the ellipsis is the innermost element, not the last element as in all other pack expansions.

      Note:Ts (&...)[N] is not allowed because the C++11 grammar requires the parenthesized ellipsis to have a name:CWG issue 1488.

      [edit]Template parameter list

      Pack expansion may appear in a template parameter list:

      template<typename...T>struct value_holder{template<T...Values>// expands to a constant template parameterstruct apply{};// list, such as <int, char, int(&)[5]>};

      [edit]Base specifiers and member initializer lists

      A pack expansion may designate the list of base classes in aclass declaration. Typically, this also means that the constructor needs to use a pack expansion in themember initializer list to call the constructors of these bases:

      template<class...Mixins>class X:public Mixins...{public:    X(const Mixins&...mixins): Mixins(mixins)...{}};

      [edit]Lambda captures

      Pack expansion may appear in the capture clause of alambda expression:

      template<class...Args>void f(Args...args){auto lm=[&, args...]{return g(args...);};    lm();}

      [edit]Thesizeof... operator

      Thesizeof... operator is classified as a pack expansion as well:

      template<class...Types>struct count{staticconststd::size_t value= sizeof...(Types);};

      Dynamic exception specifications

      The list of exceptions in adynamic exception specification may also be a pack expansion:

      template<class...X>void func(int arg)throw(X...){// ... throw different Xs in different situations}
      (until C++17)

      [edit]Alignment specifier

      Pack expansions are allowed in both the lists of types and the lists of expressions used by the keywordalignas. The instantiations are space-separated:

      template<class...T>struct Align{    alignas(T...)unsignedchar buffer[128];}; Align<int,short> a;// the alignment specifiers after expansion are// alignas(int) alignas(short)// (no comma in between)

      [edit]Attribute list

      Pack expansions are allowed in the lists ofattributes, if permitted by the attribute's specification. For example:

      template<int...args>[[vendor::attr(args)...]]void* f();

      Fold expressions

      Infold expressions, the pattern is the entire subexpression that does not contain an unexpanded pack.

      Using-declarations

      Inusing declarations, ellipsis may appear in the list of declarators, this is useful when deriving from a template parameter pack:

      template<typename...bases>struct X: bases...{using bases::g...;};X<B, D> x;// OK: B::g and D::g introduced
      (since C++17)


      Pack indexing

      Inpack indexing, the pack expansion contains an unexpanded pack followed by an ellipsis and subscript. The pattern of pack indexing expression is anidentifier, while the pattern of pack indexing specifier is atypedef-name.

      constevalauto first_plus_last(auto...args){return 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 declarations

      In classfriend declarations, each type specifier can be followed by an ellipsis:

      struct C{};struct E{struct Nested;}; template<class...Ts>class R{friend Ts...;}; template<class...Ts,class...Us>class R<R<Ts...>, R<Us...>>{friend Ts::Nested..., Us...;}; R<C, E> rce;// classes C and E are friends of R<C, E>R<R<E>, R<C,int>> rr;// E::Nested and C are friends of R<R<E>, R<C, int>>

      Fold expanded constraints

      Infold expanded constraints, the pattern is the constraint of that fold expanded constraint.

      A fold expanded constraint is not instantiated.

      (since C++26)

      [edit]Notes

      This section is incomplete
      Reason: a few words about partial specializations and other ways to access individual elements? Mention recursion vs logarithmic vs shortcuts such as fold expressions
      Feature-test macroValueStdFeature
      __cpp_variadic_templates200704L(C++11)Variadic templates
      __cpp_pack_indexing202311L(C++26)Pack indexing

      [edit]Example

      The below example defines a function similar tostd::printf, that replace each occurrence of the character% in the format string with a value.

      The first overload is called when only the format string is passed and there is no parameter expansion.

      The second overload contains a separate template parameter for the head of the arguments and a parameter pack, this allows the recursive call to pass only the tail of the parameters until it becomes empty.

      Targs is the template parameter pack andFargs is the function parameter pack.

      Run this code
      #include <iostream> void tprintf(constchar* format)// base function{std::cout<< format;} template<typename T,typename...Targs>void tprintf(constchar* format, T value, Targs...Fargs)// recursive variadic function{for(;*format!='\0'; format++){if(*format=='%'){std::cout<< value;            tprintf(format+1, Fargs...);// recursive callreturn;}std::cout<<*format;}} int main(){    tprintf("% world% %\n","Hello",'!',123);}

      Output:

      Hello world! 123

      [edit]Defect reports

      The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

      DRApplied toBehavior as publishedCorrect behavior
      CWG 1533C++11a pack expansion could occur in a member initializer for a membernot allowed
      CWG 2717C++11instantiations of alignment specifiers were comma-separatedthey are space-separated

      [edit]See also

      Function template Defines a family of functions
      Class template Defines a family of classes
      sizeof... Queries the number of elements in a pack
      C-style variadic function Takes a variable number of arguments
      Preprocessor macros Can be variadic as well
      Fold expression Reduces a pack over a binary operator
      Pack indexing Accesses the element of a pack at specified index
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/pack&oldid=182710"

      [8]ページ先頭

      ©2009-2025 Movatter.jp