Variadic arguments
Позволяет функции принимать любое количество дополнительных аргументов.
Функция является вариативной, если последний параметр в её списке параметров является многоточием ( ... ).
| Запятая перед многоточием может быть опущена. | (устарело в C++26) |
// функция объявлена следующим образом int printx(const char* fmt, ...); int printx(const char* fmt...); // аналогично предыдущему, но устарело с C++26 // может быть вызвана с одним или более аргументами: printx("hello world"); printx("a=%d b=%d", a, b); int printy(..., const char* fmt); // ошибка: ... может быть только последним параметром int printz(...); // корректно, но аргументы не могут быть переносимо доступны
|
Это отличается от раскрытия parameter pack функции, которое обозначается многоточием, являющимся частью декларатора параметра, а не многоточием как самостоятельным параметром. Как раскрытие parameter pack, так и «вариативное» многоточие могут встречаться в объявлении шаблона функции, как в случае с std::is_function . |
(since C++11) |
Содержание |
Продвижения аргументов по умолчанию
При вызове вариативной функции, после преобразований lvalue-в-rvalue, массива-в-указатель и функции-в-указатель conversions , каждый аргумент, являющийся частью списка переменных аргументов, подвергается дополнительным преобразованиям, известным как default argument promotions :
|
(начиная с C++11) |
- float аргументы преобразуются в double как при повышении типа с плавающей точкой .
- bool , char , short и неограниченные перечисления преобразуются в int или более широкие целочисленные типы как при целочисленном повышении .
Не-POD классы (до C++11) Scoped перечисления и классы с подходящим нетривиальным конструктором копирования, подходящим нетривиальным конструктором перемещения или нетривиальным деструктором (начиная с C++11) условно поддерживаются в потенциально вычисляемых вызовах с семантикой, определяемой реализацией (эти типы всегда поддерживаются в невычисляемых вызовах ).
Поскольку вариадические параметры имеют самый низкий приоритет для целей overload resolution , они обычно используются как универсальные резервные варианты в SFINAE .
В теле функции, использующей переменное количество аргументов, значения этих аргументов могут быть доступны с помощью
<cstdarg>
библиотечных средств
:
|
Определено в заголовочном файле
<cstdarg>
|
|
|
обеспечивает доступ к аргументам вариативной функции
(функция-макрос) |
|
|
получает доступ к следующему аргументу вариативной функции
(функция-макрос) |
|
|
(C++11)
|
создает копию аргументов вариативной функции
(функция-макрос) |
|
завершает обход аргументов вариативной функции
(функция-макрос) |
|
|
содержит информацию, необходимую для работы
va_start
,
va_arg
,
va_end
и
va_copy
(определение типа) |
|
Поведение макроса va_start не определено, если последний параметр перед многоточием имеет ссылочный тип, или имеет тип, который не совместим с типом, получающимся в результате стандартных приведений аргументов.
|
Если расширение пакета или сущность, полученная в результате захвата лямбда-выражения , используется в качестве последнего параметра в va_start , программа является некорректной, диагностика не требуется. |
(since C++11) |
Альтернативы
|
(начиная с C++11) |
Примечания
В языке программирования C до стандарта C23 по крайней мере один именованный параметр должен предшествовать параметру с многоточием, поэтому R printz ( ... ) ; не является допустимым до C23. В C++ такая форма разрешена, даже если аргументы, передаваемые такой функции, недоступны, и обычно используется как резервная перегрузка в SFINAE , используя наименьший приоритет преобразования с многоточием в разрешении перегрузки .
Этот синтаксис для вариативных аргументов был введён в C++ 1983 года без запятой перед многоточием. Когда C89 заимствовал прототипы функций из C++, он заменил синтаксис на требующий запятую. Для совместимости C++98 принимает как C++-стиль f ( int n... ) так и C-стиль f ( int n, ... ) . Исходная грамматика в C++-стиле устарела начиная с C++26.
|
Запятая может использоваться в сокращенных шаблонах функций, чтобы заставить многоточие обозначать вариативную функцию вместо вариативного шаблона:
void
f1
(
auto
...
)
;
// same as template<class... Ts> void f3(Ts...)
|
(since C++20) |
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 506 | C++98 |
передача аргументов не-POD классов в
эллипсис приводила к неопределённому поведению |
передача таких аргументов является
условно-поддерживаемой с определяемой реализацией семантикой |
| CWG 634 | C++98 |
условно-поддерживаемые классовые типы
нарушали работу некоторых идиом SFINAE |
всегда поддерживаются, если не вычисляются |
| CWG 2247 | C++11 |
отсутствовали ограничения на передачу параметр-пака
или захвата лямбды в
va_start
|
сделано некорректным,
диагностика не требуется |
| CWG 2347 | C++11 |
было неясно, подлежат ли ограниченные перечисления, передаваемые в
эллипсис, стандартным продвижениям аргументов |
передача ограниченных перечислений
является условно-поддерживаемой с определяемой реализацией семантикой |
Смотрите также
|
C documentation
для
Variadic arguments
|
|
|
C documentation
для
Implicit conversions
|