Variadic arguments
Permite que una función acepte cualquier número de argumentos adicionales.
Una función es variádica si el último parámetro de su lista de parámetros es una elipsis ( ... ).
| La coma que precede a los puntos suspensivos puede omitirse. | (obsoleto en C++26) |
// la función declarada de la siguiente manera int printx(const char* fmt, ...); int printx(const char* fmt...); // igual que la anterior, pero obsoleta desde C++26 // puede ser llamada con uno o más argumentos: printx("hello world"); printx("a=%d b=%d", a, b); int printy(..., const char* fmt); // error: ... solo puede ser el último parámetro int printz(...); // válido, pero los argumentos no pueden accederse de forma portable
|
Esto es diferente de una expansión de parameter pack de función, que se indica mediante puntos suspensivos que forman parte de un declarador de parámetro, en lugar de puntos suspensivos que son un parámetro por sí solos. Tanto la expansión de parameter pack como los puntos suspensivos "variádicos" pueden aparecer en la declaración de una plantilla de función, como en el caso de std::is_function . |
(since C++11) |
Contenidos |
Promociones predeterminadas de argumentos
Cuando se llama a una función variádica, después de las conversiones de lvalue-a-rvalue, array-a-puntero y función-a-puntero conversions , cada argumento que forma parte de la lista de argumentos variables sufre conversiones adicionales conocidas como default argument promotions :
|
(desde C++11) |
- float los argumentos se convierten a double como en la promoción de punto flotante .
- bool , char , short , y las enumeraciones no delimitadas se convierten a int o tipos enteros más amplios como en la promoción entera .
Tipos de clase no-POD (hasta C++11) Enumeraciones con ámbito y tipos de clase con un constructor de copia no trivial elegible, un constructor de movimiento no trivial elegible, o un destructor no trivial (desde C++11) están condicionalmente soportados en llamadas potencialmente evaluadas con semántica definida por la implementación (estos tipos siempre están soportados en llamadas no evaluadas ).
Debido a que los parámetros variádicos tienen el rango más bajo para el propósito de resolución de sobrecarga , comúnmente se utilizan como respaldo general en SFINAE .
Dentro del cuerpo de una función que utiliza argumentos variádicos, los valores de estos argumentos pueden accederse utilizando las
<cstdarg>
facilidades de la biblioteca
:
|
Definido en el encabezado
<cstdarg>
|
|
|
habilita el acceso a los argumentos de función variádicos
(macro de función) |
|
|
accede al siguiente argumento de función variádico
(macro de función) |
|
|
(C++11)
|
realiza una copia de los argumentos de función variádicos
(macro de función) |
|
finaliza el recorrido de los argumentos de función variádicos
(macro de función) |
|
|
contiene la información necesaria para
va_start
,
va_arg
,
va_end
, y
va_copy
(typedef) |
|
El comportamiento de la macro va_start es indefinido si el último parámetro antes de los puntos suspensivos tiene tipo de referencia, o tiene un tipo que no es compatible con el tipo que resulta de las promociones de argumentos por defecto.
|
Si una expansión de paquete o una entidad resultante de una captura lambda se utiliza como el último parámetro en va_start , el programa está mal formado, no se requiere diagnóstico. |
(since C++11) |
Alternativas
|
(desde C++11) |
Notas
En el lenguaje de programación C hasta C23, al menos un parámetro nombrado debe aparecer antes del parámetro de elipsis, por lo que R printz ( ... ) ; no es válido hasta C23. En C++, esta forma está permitida aunque los argumentos pasados a dicha función no sean accesibles, y se utiliza comúnmente como la sobrecarga de respaldo en SFINAE , aprovechando la prioridad más baja de la conversión de elipsis en overload resolution .
Esta sintaxis para argumentos variádicos fue introducida en C++ de 1983 sin la coma antes de la elipsis. Cuando C89 adoptó los prototipos de función de C++, reemplazó la sintaxis con una que requiere la coma. Por compatibilidad, C++98 acepta tanto el estilo C++ f ( int n... ) como el estilo C f ( int n, ... ) . La gramática original de estilo C++ está obsoleta desde C++26.
|
La coma puede utilizarse en plantillas de función abreviadas para hacer que la elipsis signifique una función variádica en lugar de una plantilla variádica:
void
f1
(
auto
...
)
;
// same as template<class... Ts> void f3(Ts...)
|
(since C++20) |
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.
| DR | Se aplica a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 506 | C++98 |
pasar argumentos de clase no-POD a una
elipsis resultaba en comportamiento indefinido |
pasar dichos argumentos es
condicionalmente soportado con semántica definida por la implementación |
| CWG 634 | C++98 |
los tipos de clase condicionalmente soportados
impedían el funcionamiento de algunos idioms SFINAE |
siempre soportado si no se evalúa |
| CWG 2247 | C++11 |
no había restricción sobre pasar paquetes de parámetros
o capturas de lambda a
va_start
|
se considera incorrecto,
no se requiere diagnóstico |
| CWG 2347 | C++11 |
no estaba claro si las enumeraciones con ámbito pasadas a
una elipsis están sujetas a promociones de argumentos por defecto |
pasar enumeraciones con ámbito
es condicionalmente soportado con semántica definida por la implementación |
Véase también
|
Documentación de C
para
Argumentos variádicos
|
|
|
Documentación de C
para
Conversiones implícitas
|