Parameter packs (C++11)

A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.

In the template definition, a parameter pack is treated as a single parameter. In the template instantiation, a parameter pack is expanded and the correct number of the parameters are created.

According to the context where a parameter pack is used, the parameter pack can be either a template parameter pack or a function parameter pack.

Template parameter packs

A template parameter pack is a template parameter that represents any number (including zero) of template parameters. Syntactically, a template parameter pack is a template parameter specified with an ellipsis. Consider the following example.

template<class...A> struct container{}; 
template<class...B> void func();

In this example, A and B are template parameter packs.

According to the type of the parameters contained in a template parameter pack, there are three kinds of template parameter packs:

  • Type parameter packs
  • Non-type parameter packs
  • Template template parameter packs

A type parameter pack represents zero or more type template parameters. Similarly, a non-type parameter pack represents zero or more non-type template parameters.

Note: Template template parameter packs are not supported in 7.3 ILE C++ Compiler.

The following example shows a type parameter pack:

template<class...T> class X{};

X<> a;                    // the parameter list is empty 
X<int> b;                 // the parameter list has one item
X<int, char, float> c;    // the parameter list has three items 

In this example, the type parameter pack T is expanded into a list of zero or more type template parameters.

The following example shows a non-type parameter pack:

template<bool...A> class X{};

X<> a;                    // the parameter list is empty 
X<true> b;                // the parameter list has one item
X<true, false, true> c;   // the parameter list has three items 

In this example, the non-type parameter pack A is expanded into a list of zero or more non-type template parameters.

In a context where template arguments can be deduced; for example, function templates and class template partial specializations, a template parameter pack does not need to be the last template parameter of a template. In this case, you can declare more than one template parameter pack in the template parameter list. However, if template arguments cannot be deduced, you can declare at most one template parameter pack in the template parameter list, and the template parameter pack must be the last template parameter. Consider the following example:

// error
template<class...A, class...B>struct container1{};

// error
template<class...A,class B>struct container2{};

In this example, the compiler issues two error messages. One error message is for class template container1 because container1 has two template parameter packs A and B that cannot be deduced. The other error message is for class template container2 because template parameter pack A is not the last template parameter of container2, and A cannot be deduced.

Default arguments cannot be used for a template parameter pack. Consider the following example:

template<typename...T=int> struct foo1{};

In this example, the compiler issues an error message because the template parameter pack T is given a default argument int.

Function parameter packs

A function parameter pack is a function parameter that represents zero or more function parameters. Syntactically, a function parameter pack is a function parameter specified with an ellipsis.

In the definition of a function template, a function parameter pack uses a template parameter pack in the function parameters. The template parameter pack is expanded by the function parameter pack. Consider the following example:

template<class...A> void func(A...args) 

In this example, A is a template parameter pack, and args is a function parameter pack. You can call the function with any number (including zero) of arguments:

func();                  // void func(); 
func(1);                 // void func(int); 
func(1,2,3,4,5);         // void func(int,int,int,int,int);
func(1,'x', aWidget);    // void func(int,char,widget);  

A function parameter pack is a trailing function parameter pack if it is the last function parameter of a function template. Otherwise, it is a non-trailing function parameter pack . A function template can have trailing and non-trailing function parameter packs. A non-trailing function parameter pack can be deduced only from the explicitly specified arguments when the function template is called. If the function template is called without explicit arguments, the non-trailing function parameter pack must be empty, as shown in the following example:

#include <cassert>

template<class...A, class...B> void func(A...arg1,int sz1, int sz2, B...arg2)  
{
   assert( sizeof...(arg1) == sz1);
   assert( sizeof...(arg2) == sz2);
}

int main(void)
{
   //A:(int, int, int), B:(int, int, int, int, int) 
   func<int,int,int>(1,2,3,3,5,1,2,3,4,5);

   //A: empty, B:(int, int, int, int, int)
   func(0,5,1,2,3,4,5);
   return 0;
}

In this example, function template func has two function parameter packs arg1 and arg2. arg1 is a non-trailing function parameter pack, and arg2 is a trailing function parameter pack. When func is called with three explicitly specified arguments as func<int,int,int>(1,2,3,3,5,1,2,3,4,5), both arg1 and arg2 are deduced successfully. When func is called without explicitly specified arguments as func(0,5,1,2,3,4,5), arg2 is deduced successfully and arg1 is empty. In this example, the template parameter packs of function template func can be deduced, so func can have more than one template parameter pack.