Variadic arguments
Ermöglicht es einer Funktion, eine beliebige Anzahl zusätzlicher Argumente zu akzeptieren.
Eine Funktion ist variadisch, wenn der letzte Parameter ihrer Parameterliste eine Ellipse ( ... ) ist.
| Das Komma vor der Auslassungspunkten kann weggelassen werden. | (deprecated in C++26) |
// die Funktion wird wie folgt deklariert int printx(const char* fmt, ...); int printx(const char* fmt...); // wie oben, aber seit C++26 veraltet // kann mit einem oder mehr Argumenten aufgerufen werden: printx("hello world"); printx("a=%d b=%d", a, b); int printy(..., const char* fmt); // Fehler: ... kann nur der letzte Parameter sein int printz(...); // gültig, aber die Argumente können nicht portabel zugegriffen werden
|
Dies unterscheidet sich von einer Parameter Pack -Entfaltung, die durch eine Ellipse angezeigt wird, die Teil eines Parameterdeklarators ist, anstatt dass eine Ellipse allein ein Parameter ist. Sowohl Parameter Pack-Entfaltung als auch die "variadische" Ellipse können in der Deklaration einer Funktionsvorlage auftreten, wie im Fall von std::is_function . |
(since C++11) |
Inhaltsverzeichnis |
Standardargument-Promotionen
Wenn eine variadische Funktion aufgerufen wird, erfolgen nach Lvalue-zu-Rvalue-, Array-zu-Zeiger- und Funktion-zu-Zeiger- Konvertierungen zusätzliche Konvertierungen für jedes Argument, das Teil der variablen Argumentliste ist, bekannt als Default Argument Promotions :
|
(seit C++11) |
- float Argumente werden wie bei der Gleitkomma-Promotion in double konvertiert.
- bool , char , short und unbegrenzte Enumerationen werden wie bei der Ganzzahl-Promotion in int oder breitere Ganzzahltypen konvertiert.
Non-POD-Klassentypen (bis C++11) Bereichsbezogene Aufzählungstypen und Klassentypen mit einem geeigneten nicht-trivialen Kopierkonstruktor, einem geeigneten nicht-trivialen Verschiebekonstruktor oder einem nicht-trivialen Destruktor (seit C++11) werden in potenziell ausgewerteten Aufrufen mit implementierungsdefinierter Semantik bedingt unterstützt (diese Typen werden in nicht ausgewerteten Aufrufen immer unterstützt).
Da variadische Parameter für den Zweck der Überladungsauflösung den niedrigsten Rang haben, werden sie häufig als Auffangfallbacks in SFINAE verwendet.
Im Rumpf einer Funktion, die variadische Argumente verwendet, können die Werte dieser Argumente mithilfe der
<cstdarg>
Bibliotheksfunktionen
abgerufen werden:
|
Definiert im Header
<cstdarg>
|
|
|
ermöglicht den Zugriff auf variadische Funktionsargumente
(Funktionsmakro) |
|
|
greift auf das nächste variadische Funktionsargument zu
(Funktionsmakro) |
|
|
(C++11)
|
erstellt eine Kopie der variadischen Funktionsargumente
(Funktionsmakro) |
|
beendet die Verarbeitung der variadischen Funktionsargumente
(Funktionsmakro) |
|
|
enthält die für
va_start
,
va_arg
,
va_end
und
va_copy
benötigten Informationen
(Typdefinition) |
|
Das Verhalten des va_start Makros ist undefiniert, wenn der letzte Parameter vor den Auslassungspunkten einen Referenztyp hat oder einen Typ aufweist, der nicht kompatibel mit dem Typ ist, der sich aus den Standardargument-Promotions ergibt.
|
Wenn eine Pack-Erweiterung oder eine Entität, die aus einer Lambda-Capture resultiert, als letzter Parameter in va_start verwendet wird, ist das Programm fehlerhaft, keine Diagnose erforderlich. |
(seit C++11) |
Alternativen
|
(seit C++11) |
Hinweise
In der Programmiersprache C bis C23 muss mindestens ein benannter Parameter vor dem Ellipsen-Parameter erscheinen, daher ist R printz ( ... ) ; bis C23 nicht gültig. In C++ ist diese Form erlaubt, obwohl die an solche Funktionen übergebenen Argumente nicht zugänglich sind, und wird häufig als Fallback-Overload in SFINAE verwendet, wobei die niedrigste Priorität der Ellipsen-Konvertierung in der Überladungsauflösung ausgenutzt wird.
Diese Syntax für variadische Argumente wurde 1983 in C++ ohne das Komma vor der Ellipse eingeführt. Als C89 Funktionsprototypen von C++ übernahm, ersetzte es die Syntax durch eine, die das Komma erfordert. Aus Kompatibilitätsgründen akzeptiert C++98 sowohl den C++-Stil f ( int n... ) als auch den C-Stil f ( int n, ... ) . Die ursprüngliche C++-Grammatik ist seit C++26 als veraltet markiert.
|
Das Komma kann in abgekürzten Funktionsvorlagen verwendet werden, um die Ellipse als variadische Funktion statt als variadische Vorlage zu kennzeichnen:
void
f1
(
auto
...
)
;
// same as template<class... Ts> void f3(Ts...)
|
(since C++20) |
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 506 | C++98 |
Übergabe von Nicht-POD-Klassenargumenten an eine
Ellipse führte zu undefiniertem Verhalten |
Übergabe solcher Argumente ist
bedingt unterstützt mit implementierungsdefinierter Semantik |
| CWG 634 | C++98 |
bedingt unterstützte Klassentypen
ließen einige SFINAE-Idiome nicht funktionieren |
immer unterstützt wenn nicht ausgewertet |
| CWG 2247 | C++11 |
keine Einschränkung bei Übergabe von Parameter-Packs
oder Lambda-Captures an
va_start
|
als fehlerhaft eingestuft,
keine Diagnose erforderlich |
| CWG 2347 | C++11 |
war unklar, ob an eine Ellipse übergebene
scopierte Enumerationen Standardargument-Promotions unterliegen |
Übergabe scopierter Enumerationen
ist bedingt unterstützt mit implementierungsdefinierter Semantik |
Siehe auch
|
C-Dokumentation
für
Variadic arguments
|
|
|
C-Dokumentation
für
Implicit conversions
|