Allows a function to accept any number of extra arguments.
A function is a variadic if the last parameter of its
is an ellipsis (...).
The comma preceding the ellipsis can be omitted.(deprecated in C++26)// the function declared as followsintprintx(constchar*fmt,...);intprintx(constchar*fmt...);// same as above, but deprecated since C++26// may be called with one or more arguments:printx("hello world");printx("a=%d b=%d",a,b);intprinty(...,constchar*fmt);// error: ... can only be the last parameterintprintz(...);// valid, but the arguments cannot be accessed portablyThis is different from a function
expansion, which is indicated by an ellipsis that is a part of a parameter declarator, rather than an ellipsis being a parameter alone. Both parameter pack expansion and the “variadic” ellipsis may appear in the declaration of a function template, as in the case of
.
(since C++11)Default argument promotions
When a variadic function is called, after lvalue-to-rvalue, array-to-pointer, and function-to-pointer
, each argument that is a part of the variable argument list undergoes additional conversions known as default argument promotions:
float arguments are converted to double as in
.
bool, char, short, and unscoped enumerations are converted to int or wider integer types as in
.
Non-POD class types(until C++11)Scoped enumerations and class types with an eligible non-trivial copy constructor, an eligible non-trivial move constructor, or a non-trivial destructor(since C++11) are conditionally-supported in potentially-evaluated calls with implementation-defined semantics (these types are always supported in
).
Because variadic parameters have the lowest rank for the purpose of
, they are commonly used as the catch-all fallbacks in
.
Within the body of a function that uses variadic arguments, the values of these arguments may be accessed using the
:
Defined in header
enables access to variadic function arguments
(function macro)
accesses the next variadic function argument
(function macro)
(C++11)
makes a copy of the variadic function arguments
(function macro)
ends traversal of the variadic function arguments
(function macro)
holds the information needed by
,
,
, and
(typedef)
The behavior of the
macro is undefined if the last parameter before the ellipsis has reference type, or has type that is not
with the type that results from default argument promotions.
Alternatives
can also be used to create functions that take variable number of arguments. They are often the better choice because they do not impose restrictions on the types of the arguments, do not perform integral and floating-point promotions, and are type safe.
If all variable arguments share a common type, a
provides a convenient mechanism (albeit with a different syntax) for accessing variable arguments. In this case however the arguments cannot be modified since
can only provide a const pointer to its elements.
(since C++11)Notes
In the C programming language until C23, at least one named parameter must appear before the ellipsis parameter, so Rprintz(...); is not valid until C23. In C++, this form is allowed even though the arguments passed to such function are not accessible, and is commonly used as the fallback overload in
, exploiting the lowest priority of the ellipsis conversion in
.
This syntax for variadic arguments was introduced in 1983 C++ without the comma before the ellipsis. When C89 adopted function prototypes from C++, it replaced the syntax with one requiring the comma. For compatibility, C++98 accepts both C++-style f(intn...) and C-style f(intn,...). The original C++-style grammar is deprecated since C++26.
The comma can be used in abbreviated function templates to make the ellipsis signify a variadic function instead of a variadic template:
voidf1(auto...);// same as template<class... Ts> void f3(Ts...)
voidf2(auto,...);// same as template<class T> void f3(T, ...)
(since C++20)Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior
C++98 passing non-POD class arguments to an
ellipsis resulted in undefined behavior passing such arguments is
conditionally-supported with
implementation-defined semantics
C++98 conditionally-supported class types
made some SFINAE idioms not work always supported if unevaluated
C++11 no restriction on passing parameter
pack or lambda capture to va_startmade ill-formed,
no diagnostic required
C++11 it was unclear whether scoped enumerations passed to
an ellipsis are subject to default argument promotions passing scoped enumerations
is conditionally-supported with
implementation-defined semantics See also