In the context of variadic template, the ellipsis ...
is used to either pack or unpack parameters/arguments in a template definition, depending on the relative position where it appears:
- it unpacks the template parameter pack if it appears on the right side of an expression (call this expression pattern for a moment)
- or it's a pack argument if it appears on left side of the name:
...thing // pack : appears as template arguments
thing... // unpack : appears when consuming the arguments
The rule is that whatever pattern is on the left side of ...
is repeated — the unpacked patterns (call them expressions now) are separated by comma ,
.
It can be best understood by some examples. Suppose you have this function template:
template<typename ...T> //pack
void f(T ... args) //pack
{
// here are unpack patterns
g( args... ); //pattern = args
h( x(args)... ); //pattern = x(args)
m( y(args...) ); //pattern = args (as argument to y())
n( z<T>(args)... ); //pattern = z<T>(args)
}
Now if I call this function passing T
as {int, char, short}
, then each of the function call is expanded as:
g( arg0, arg1, arg2 );
h( x(arg0), x(arg1), x(arg2) );
m( y(arg0, arg1, arg2) );
n( z<int>(arg0), z<char>(arg1), z<short>(arg2) );
In the code you posted, std::forward
follows the fourth pattern illustrated by n()
function call.
Note the difference between x(args)...
and y(args...)
above!
You can use ...
to initialize an array also as:
struct data_info
{
boost::any data;
std::size_t type_size;
};
std::vector<data_info> v{{args, sizeof(T)}...}; //pattern = {args, sizeof(T)}
which is expanded to this:
std::vector<data_info> v
{
{arg0, sizeof(int)},
{arg1, sizeof(char)},
{arg2, sizeof(short)}
};
I just realized a pattern could even include access specifier such as public
, as shown in the following example:
template<typename ... Mixins>
struct mixture : public Mixins ... //pattern = public Mixins
{
//code
};
In this example, the pattern is expanded as:
struct mixture__instantiated : public Mixin0, public Mixin1, .. public MixinN
That is, mixture
derives publicly from all the base classes.