Allows a function to accept any number of arguments.
Indicated by the parameter of the form ...
which must appear last in the parameter-list of a function declaration.
Where syntactically correct, , ...
may be replaced by ...
.
// the function declared as follows int printx(const char* fmt, ...); // may be called with one or more arguments: printx("hello world"); printx("a=%d b=%d", a, b); int printx(const char* fmt...); // same as above (comma is optional) int printy(..., const char* fmt); // error: ... must be the last int printz(...); // valid, but the arguments cannot be accessed portably
Note: this is different from a function parameter pack expansion, which is indicated by an ellipsis that is a part of a parameter declarator, rather than an ellipsis that appears as a parameter on its own. Both parameter pack expansion and the ellipsis parameter may appear in the declaration of a function template, as in the case of std::is_function
.
When a variadic function is called, after lvalue-to-rvalue, array-to-pointer, and function-to-pointer conversions, each argument that is a part of the variable argument list undergoes additional conversions known as default argument promotions:
std::nullptr_t
is converted to void*
float
arguments are converted to double
as in floating-point promotion bool
, char
, short
, and unscoped enumerations are converted to int
or wider integer types as in integer promotion Only arithmetic, enumeration, pointer, pointer to member, and class type arguments are allowed (except class types with non-trivial copy constructor, non-trivial move constructor, or a non-trivial destructor, which are conditionally-supported with implementation-defined semantics).
Because variadic parameters have the lowest rank for the purpose of overload resolution, they are commonly used as the catch-all fallbacks in SFINAE.
Within the body of a function that uses variadic arguments, the values of these arguments may be accessed using the <cstdarg> library facilities:
Defined in header <cstdarg> |
|
---|---|
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 va_start, va_arg, va_end, and va_copy (typedef) |
The behavior of the va_start
macro is undefined if the last parameter before the ellipsis has reference type, or has type that is not compatible with the type that results from default argument promotions.
std::initializer_list
provides a convenient mechanism (albeit with a different syntax) for accessing variable arguments. In this case however the arguments cannot be modified since std::initializer_list
can only provide a const pointer to its elements. (since C++11) In the C programming language, at least one named parameter must appear before the ellipsis parameter, so printz(...);
is not valid. 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 SFINAE, exploiting the lowest priority of the ellipsis conversion in overload resolution.
This syntax for variadic arguments was introduced in 1987 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(int n...)
and C-style f(int n, ...)
.
C documentation for Variadic arguments |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/language/variadic_arguments