Variadische Argumente
Ermöglicht einer Funktion, eine beliebige Anzahl zusätzlicher Argumente anzunehmen.
Eine Funktion ist variadisch, wenn der letzte Parameter ihrer Parameterliste ein Auslassungszeichen (...) ist.
| Das Komma vor dem Auslassungszeichen kann weggelassen werden. | (veraltet in C++26) |
// the function declared as follows int printx(const char* fmt, ...); int printx(const char* 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); int printy(..., const char* fmt); // error: ... can only be the last parameter int printz(...); // valid, but the arguments cannot be accessed portably
|
Dies unterscheidet sich von einer Parameterpaketexpansion einer Funktion, die durch ein Auslassungszeichen angezeigt wird, das Teil eines Deklarators ist, anstatt dass ein Auslassungszeichen allein ein Parameter ist. Sowohl Parameterpaketexpansion als auch das „variadische“ Auslassungszeichen können in der Deklaration einer Funktion-Vorlage vorkommen, wie im Fall von std::is_function. |
(seit C++11) |
Inhalt |
[bearbeiten] Standard-Argument-Promotions
Wenn eine variadische Funktion aufgerufen wird, durchlaufen nach lvalue-zu-rvalue, Array-zu-Zeiger und Funktion-zu-Zeiger Konvertierungen alle Argumente, die Teil der variablen Argumentliste sind, zusätzliche Konvertierungen, die als *Standard-Argument-Promotions* bezeichnet werden.
|
(seit C++11) |
- float-Argumente werden wie bei der Gleitkomma-Promotion in double konvertiert.
- bool, char, short und nicht-scoped Aufzählungen werden wie bei der Ganzzahl-Promotion in int oder breitere Ganzzahldatentypen konvertiert.
Nicht-POD-Klassentypen(bis C++11)Scoped Aufzählungen und Klassentypen mit einem geeigneten nicht-trivialen Kopierkonstruktor, einem geeigneten nicht-trivialen Move-Konstruktor oder einem nicht-trivialen Destruktor(seit C++11) sind in potenziell ausgewerteten Aufrufen bedingt unterstützt mit implementierungsdefinierten Semantiken (diese Typen werden in unevaluierten Aufrufen immer unterstützt).
Da variadische Parameter für die Überladungsauflösung den niedrigsten Rang haben, werden sie üblicherweise als Catch-all-Fallback in SFINAE verwendet.
Innerhalb des Körpers einer Funktion, die variadische Argumente verwendet, können die Werte dieser Argumente mithilfe der <cstdarg> Bibliotheksfunktionen zugegriffen 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 Durchquerung der variadischen Funktionsargumente (Funktionsmakro) | |
| hält die von va_start, va_arg, va_end und va_copy benötigten Informationen (typedef) | |
Das Verhalten des Makros va_start ist undefiniert, wenn der letzte Parameter vor dem Auslassungszeichen einen Referenztyp hat oder einen Typ hat, der nicht mit dem Typ, der sich aus Standard-Argument-Promotions ergibt, kompatibel ist.
|
Wenn eine Paketexpansion oder eine Entität, die aus einer Lambda-Erfassung resultiert, als letzter Parameter in va_start verwendet wird, ist das Programm ill-formed, keine Diagnose erforderlich. |
(seit C++11) |
[bearbeiten] Alternativen
|
(seit C++11) |
[bearbeiten] Hinweise
In der Programmiersprache C bis C23 muss mindestens ein benannter Parameter vor dem Auslassungsparameter erscheinen, daher ist R printz(...); bis C23 nicht gültig. In C++ ist diese Form erlaubt, obwohl die an eine solche Funktion übergebenen Argumente nicht zugänglich sind, und wird üblicherweise als Fallback-Überladung in SFINAE verwendet, wobei die niedrigste Priorität der Auslassungskonvertierung in der Überladungsauflösung ausgenutzt wird.
Diese Syntax für variadische Argumente wurde 1983 in C++ ohne das Komma vor dem Auslassungszeichen eingeführt. Als C89 die Funktionsprototypen von C++ übernahm, ersetzte es die Syntax durch eine, die das Komma erforderte. 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++-Stil-Grammatik ist seit C++26 veraltet.
|
Das Komma kann in abgekürzten Funktion-Vorlagen verwendet werden, um das Auslassungszeichen für eine variadische Funktion anstelle einer variadischen Vorlage zu kennzeichnen. void f1(auto...); // dasselbe wie template<class... Ts> void f3(Ts...) |
(seit C++20) |
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 506 | C++98 | Übergabe von Nicht-POD-Klassenargumenten an einen Auslassungspunkt führte zu undefiniertem Verhalten |
Übergabe solcher Argumente ist bedingt unterstützt mit implementierungsdefinierten Semantiken |
| CWG 634 | C++98 | bedingt unterstützte Klassentypen führten dazu, dass einige SFINAE-Idiome nicht funktionierten |
immer unterstützt, wenn nicht ausgewertet |
| CWG 2247 | C++11 | keine Einschränkung bei der Übergabe von Parameter Paket oder Lambda-Erfassung an va_start |
machte ill-formed, keine Diagnose erforderlich |
| CWG 2347 | C++11 | Es war unklar, ob Scoped-Aufzählungen übergeben werden an einen Auslassungspunkt sind Standard-Argument-Promotions unterworfen |
Übergabe von Scoped-Aufzählungen ist bedingt unterstützt mit implementierungsdefinierten Semantiken |
[bearbeiten] Siehe auch
| C-Dokumentation für Variadische Argumente
| |
| C-Dokumentation für Implizite Konvertierungen
|