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.