//
// 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) {