Namespaces
Variants
Views
Actions

Variadic functions

From cppreference.com
< cpp‎ | utility
Revision as of 10:35, 3 June 2012 by Nate (Talk | contribs)

Template:cpp/utility/variadic/sidebar

Variadic functions are functions (e.g. std::printf) which take a variable number of arguments.

Contents

Usage

To declare a variadic function, an ellipsis is used as the last parameter, e.g. int printf(const char *format, ...);. Parameters passed to a variadic function can be accessed using the following macros and types:

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
(class)

Default conversions

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.

Alternatives

  • Variadic templates 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. (since C++11)
  • If all variable arguments share a common type, a std::initializer_list provides a convenient mechanism (albeit with a different syntax) for accessing variable arguments.

Example

#include <iostream>
#include <cstdarg>
 
void simple_printf(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
 
    while (*fmt != '\0') {
        if (*fmt == 'd') {
            int i = va_arg(args, int);
            std::cout << i << '\n';
        } else if (*fmt == 'c') {
            // note automatic conversion to integral type
            int c = va_arg(args, int);
            std::cout << static_cast<char>(c) << '\n';
        } else if (*fmt == 'f') {
            double d = va_arg(args, double);
            std::cout << d << '\n';
        }
        ++fmt;
    }
 
    va_end(args);
}
 
int main()
{
    simple_printf("dcff", 3, 'a', 1.999, 42.5); 
}

Output:

3
a
1.999
42.5