16.4. Шаблоны с переменным количеством аргументов

Шаблон с переменным количеством аргументов (variadic template) — это шаблон функции или класса, способный получать переменное количество параметров. Набор таких параметров называется пакетом параметров (parameter pack). Есть два вида пакетов параметров: пакет параметров шаблона (template parameter pack), представляющий любое количество параметров шаблона, и пакет параметров функции (function parameter pack), представляющий любое количество параметров функции.

Для указания, что шаблону или функции представлен пакет параметров, используется многоточие. В списке параметров шаблона синтаксис class... или typename... означает, что следующий параметр представляет список любого количества типов; имя типа, сопровождаемое многоточием, представляет список из любого количества параметров значения заданного типа. Параметр в списке параметров функции, типом которого является пакет параметров шаблона, представляет собой пакет параметров функции. Например:

// Args - это пакет параметров шаблона; rest - пакет параметров функции

// Args представляет любое количество параметров типа шаблона

// rest представляет любое количество параметров функции

template <typename Т, typename... Args>

void foo(const T &t, const Args& ... rest);

Этот код объявляет, что fоо() — это функция с переменным количеством аргументов, у которой один параметр типа по имени T и пакет параметров шаблона по имени Args. Этот пакет представляет любое количество дополнительных параметров типа. В списке параметров функции foo() один параметр типа const& для любого типа переданного параметром Т и пакет параметров функции rest. Этот пакет представляет любое количество параметров функции.

Как обычно, компилятор выводит типы параметра шаблона из аргументов функции. Для шаблона с переменным количеством аргументов компилятор также выводит количество параметров в пакете. Рассмотрим, например, следующие вызовы:

int i = 0; double d = 3.14; string s = "how now brown cow";

foo(i, s, 42, d); // три параметра в пакете

foo(s, 42, "hi"); // два параметра в пакете

foo(d, s);        // один параметр в пакете

foo("hi");        // пустой пакет

Компилятор создаст четыре разных экземпляра функции fоо():

void foo(const int&, const string&, const int&, const double&);

void foo(const string&, const int&, const char[3]&);

void foo(const double&, const string&);

void foo(const char[3]&);

В каждом случае тип T выводится из типа первого аргумента. Остальные аргументы (если они есть) представляют количество и типы дополнительных аргументов функции.

Оператор sizeof...

Когда необходимо узнать, сколько элементов находится в пакете, можно использовать оператор sizeof.... Как и оператор sizeof (см. раздел 4.9), оператор sizeof... возвращает константное выражение (см. раздел 2.4.4) и не вычисляет свой аргумент:

template<typename ... Args> void g(Args ... args) {

 cout << sizeof...(Args) << endl; // количество параметров типа

 cout << sizeof...(args) << endl; // количество параметров функции

}

Упражнения раздела 16.4

Упражнение 16.51. Определите, что возвратят операторы sizeof...(Args) и sizeof...(rest) для каждого вызова функции foo() в этом разделе.

Упражнение 16.52. Напишите программу, проверяющую ответы на предыдущий вопрос.

Более 800 000 книг и аудиокниг! 📚

Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением

ПОЛУЧИТЬ ПОДАРОК