//
// rest представляет любое количество параметров функции
template
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
cout << sizeof...(Args) << endl; //
cout << sizeof...(args) << endl; //
}
Упражнение 16.51. Определите, что возвратят операторы sizeof...(Args) и sizeof...(rest) для каждого вызова функции foo() в этом разделе.
Упражнение 16.52. Напишите программу, проверяющую ответы на предыдущий вопрос.
В разделе 6.2.6 упоминалось, что для определения функции, способной получать переменное количество аргументов, можно использовать класс initializer_list. Однако у аргументов должен быть одинаковый тип (или типы, преобразуемые в общий тип). Функции с переменным количеством аргументов используются тогда, когда не известно ни количество, ни типы аргументов. Для примера определим функцию, подобную прежней функции error_msg(), только на сей раз обеспечим и изменение типов аргумента. Начнем с определения функции print() с переменным количеством аргументов, которая выводит содержимое заданного списка аргументов в указанный поток.
Функции с переменным количеством аргументов зачастую рекурсивны (см. раздел 6.3.2). Первый вызов обрабатывает первый аргумент в пакете и вызывает себя для остальных аргументов. Новая функция print() будет работать таким же образом — каждый вызов выводит свой второй аргумент в поток, обозначенный первым аргументом. Для остановки рекурсии следует определить также обычную функцию print(), которая получает поток и объект:
//
//
//
template
ostream &print(ostream &os, const T &t) {
return os << t; //
}
//
//
template
ostream &print(ostream &os, const T &t, const Args&... rest) {