В контексте вариативного шаблона многоточие ...
используется для распаковки пакета параметров шаблона, если он появляется в правой части выражения (вызовите этот шаблон выражения на мгновение). Правило состоит в том, что любой шаблон в левой части ...
повторяется - распакованные шаблоны (назовите их выражениями ) разделяются запятыми ,
.
Лучше всего это можно понять на нескольких примерах. Предположим, у вас есть этот шаблон функции:
template<typename ...T>
void f(T ... args)
{
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)
}
Теперь, если я вызываю эту функцию, передавая T
как {int, char, short}
, тогда каждый вызов функции расширяется как:
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) );
В опубликованном вами коде std::forward
следует четвертый шаблон, проиллюстрированный n()
вызовом функции.
Обратите внимание на разницу между x(args)...
и y(args...)
выше!
Вы также можете использовать ...
для инициализации массива как:
struct data_info
{
boost::any data;
std::size_t type_size;
};
std::vector<data_info> v{{args, sizeof(T)}...}; //pattern = {args, sizeof(T)}
который расширяется до этого:
std::vector<data_info> v
{
{arg0, sizeof(int)},
{arg1, sizeof(char)},
{arg2, sizeof(short)}
};
Я только что понял, что шаблон может даже включать спецификатор доступа, например public
, как показано в следующем примере:
template<typename ... Mixins>
struct mixture : public Mixins ... //pattern = public Mixins
{
//code
};
В этом примере шаблон раскрывается как:
struct mixture__instantiated : public Mixin0, public Mixin1, .. public MixinN
То есть, mixture
происходит публично от всех базовых классов.
Надеюсь, это поможет.
...
предшествует вводимому идентификатору. При использовании одного или обоих типов пакетов...
символ расширения следует после шаблона выражения.