Placeholder type specifiers (since C++11)
Ein Platzhalter-Typspezifizierer bezeichnet einen Platzhaltertyp , der später ersetzt wird, typischerweise durch Ableitung von einem Initialisierer .
Inhaltsverzeichnis |
Syntax
Typ-Einschränkung
(optional)
auto
|
(1) | ||||||||
Typ-Einschränkung
(optional)
decltype(auto)
|
(2) | (seit C++14) | |||||||
| type-constraint | - |
(since C++20)
ein
concept
Name, optional qualifiziert, optional gefolgt von einer Template-Argumentliste eingeschlossen in
<>
|
decltype(expr)
, wobei
expr
der Initialisierer oder die Operanden in
return-Anweisungen
ist.
Der Platzhalter
auto
kann von Modifikatoren begleitet werden, wie
const
oder
&
, die an der Typableitung teilnehmen werden.
Der Platzhalter
decltype
(
auto
)
muss der alleinige Bestandteil des deklarierten Typs sein.
(seit C++14)
|
Wenn
type-constraint
vorhanden ist, sei
Die Ableitung schlägt fehl, wenn der constraint expression ungültig ist oder false zurückgibt. |
(since C++20) |
Erklärung
Ein Platzhalter-Typspezifizierer kann in den folgenden Kontexten erscheinen:
ParameterdeklarationenIn den folgenden Parameterdeklarationen kann der Typ des deklarierten Parameters von der Syntax (1) sein:
|
(since C++14) |
|
(since C++17) |
|
(since C++20) |
Funktionsdeklarationen
Ein Platzhaltertyp kann in den Deklarationsspezifizierern für einen Funktionsdeklarator erscheinen, der einen nachgestellten Rückgabetyp enthält.
|
Ein Platzhaltertyp kann in den Deklarationsspezifizierern oder Typspezifizierern im deklarierten Rückgabetyp eines Funktionsdeklarators erscheinen. Rückgabetypableitung wird in diesem Fall angewendet. |
(seit C++14) |
auto f() -> int; // OK: f gibt int zurück auto g() { return 0.0; } // OK seit C++14: g gibt double zurück auto h(); // OK seit C++14: h's Rückgabetyp wird bei Definition abgeleitet
Variablendeklarationen
Der Typ einer Variable, die mit einem Platzhaltertyp deklariert wird, wird von ihrem Initialisierer abgeleitet. Diese Verwendung ist in einer initialisierenden Deklaration einer Variable zulässig.
Der Platzhaltertyp kann nur als einer der Deklarationsspezifizierer in der Deklarationsspezifizierer-Sequenz oder als einer der Typspezifizierer in einem nachgestellten Rückgabetyp auftreten, der den Typ angibt, der einen solchen Deklarationsspezifizierer ersetzt. In diesem Fall muss die Deklaration mindestens eine Variable deklarieren, und jede Variable muss einen nicht-leeren Initialisierer haben.
// "auto"s in Deklarationsspezifizierern auto x = 5; // OK: x hat Typ int const auto *v = &x, u = 6; // OK: v hat Typ const int*, u hat Typ const int static auto y = 0.0; // OK: y hat Typ double auto f() -> int; auto (*fp)() -> auto = f; // OK: das "auto" im Trailing-Return-Type // kann von f abgeleitet werden
Strukturierte BindungsdeklarationenDer auto -Spezifizierer kann in einer strukturierten Bindungsdeklaration verwendet werden. |
(seit C++17) |
new Ausdrücke
Ein Platzhaltertyp kann in der Typspezifizierer-Sequenz der Typ-ID eines new-Ausdrucks verwendet werden. In einer solchen Typ-ID muss der Platzhaltertyp als einer der Typspezifizierer in der Typspezifizierer-Sequenz oder als nachgestellter Rückgabetyp erscheinen, der den Typ angibt, der einen solchen Typspezifizierer ersetzt.
Funktionsstil-CastDer auto -Typspezifizierer kann als Typspezifizierer eines Funktionsstil-Casts verwendet werden. |
(seit C++23) |
Hinweise
Bis C++11 hatte auto die Semantik eines storage duration specifier .
Ein Programm, das einen Platzhaltertyp in einem Kontext verwendet, der nicht explizit oben angegeben ist, ist fehlerhaft.
Falls eine Deklaration mehrere Entitäten deklariert und die Deklarationsspezifizierer-Sequenz einen Platzhaltertyp verwendet, ist das Programm fehlerhaft, wenn eine der folgenden Bedingungen erfüllt ist:
- Einige der deklarierten Entitäten sind keine Variablen.
- Der Typ, der den Platzhaltertyp ersetzt, ist nicht in jeder Deduktion derselbe.
auto f() -> int, i = 0; // Fehler: Deklariert eine Funktion und eine Variable mit "auto" auto a = 5, b = {1, 2}; // Fehler: Unterschiedliche Typen für "auto"
Wenn eine Funktion oder Variable mit einem nicht ersetzten Platzhaltertyp durch einen Ausdruck referenziert wird, ist das Programm fehlerhaft.
auto v = 1; auto l = [&] { v++; return l;// Fehler: Der Platzhaltertyp für l wurde nicht ersetzt }; std::function<void()> p = [&] { v++; return p;// OK };
|
Das auto Schlüsselwort kann auch in einem geschachtelten Namensspezifizierer verwendet werden. Ein geschachtelter Namensspezifizierer der Form auto :: ist ein Platzhalter, der durch einen Klassen- oder Aufzählungstyp ersetzt wird, gemäß den Regeln für die constrained type Platzhalterableitung. |
(concepts TS) |
| Feature-Test-Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_decltype_auto
|
201304L
|
(C++14) | decltype ( auto ) |
Schlüsselwörter
Beispiel
#include <iostream> #include <utility> template<class T, class U> auto add(T t, U u) { return t + u; } // der Rückgabetyp ist der Typ von operator+(T, U) // perfektes Weiterleiten eines Funktionsaufrufs muss decltype(auto) verwenden // falls die aufgerufene Funktion eine Referenz zurückgibt template<class F, class... Args> decltype(auto) PerfectForward(F fun, Args&&... args) { return fun(std::forward<Args>(args)...); } template<auto n> // C++17 auto Parameterdeklaration auto f() -> std::pair<decltype(n), decltype(n)> // auto kann nicht aus Initialisierungsliste ableiten { return {n, n}; } int main() { auto a = 1 + 2; // Typ von a ist int auto b = add(1, 1.2); // Typ von b ist double static_assert(std::is_same_v<decltype(a), int>); static_assert(std::is_same_v<decltype(b), double>); auto c0 = a; // Typ von c0 ist int, enthält eine Kopie von a decltype(auto) c1 = a; // Typ von c1 ist int, enthält eine Kopie von a decltype(auto) c2 = (a); // Typ von c2 ist int&, ein Alias von a std::cout << "before modification through c2, a = " << a << '\n'; ++c2; std::cout << " after modification through c2, a = " << a << '\n'; auto [v, w] = f<0>(); // strukturierte Bindungsdeklaration auto d = {1, 2}; // OK: Typ von d ist std::initializer_list<int> auto n = {5}; // OK: Typ von n ist std::initializer_list<int> // auto e{1, 2}; // Fehler seit DR n3922, davor std::initializer_list<int> auto m{5}; // OK: Typ von m ist int seit DR n3922, davor initializer_list<int> // decltype(auto) z = { 1, 2 } // Fehler: {1, 2} ist kein Ausdruck // auto wird häufig für unbenannte Typen wie Lambda-Ausdrücke verwendet auto lambda = [](int x) { return x + 3; }; // auto int x; // gültig in C++98, Fehler ab C++11 // auto x; // gültig in C, Fehler in C++ [](...){}(c0, c1, v, w, d, n, m, lambda); // unterdrückt "unused variable" Warnungen }
Mögliche Ausgabe:
before modification through c2, a = 3 after modification through c2, a = 4
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 1265 | C++11 |
der
auto
Spezifizierer konnte verwendet werden, um eine Funktion mit einem nachgestellten
Rückgabetyp und eine Variable in einer Deklarationsanweisung zu deklarieren |
verboten |
| CWG 1346 | C++11 | eine geklammerte Ausdrucksliste konnte nicht einer auto Variable zugewiesen werden | erlaubt |
| CWG 1347 | C++11 |
eine Deklaration mit dem
auto
Spezifizierer konnte zwei Variablen
mit den Typen
T
und
std::
initializer_list
<
T
>
definieren
|
verboten |
| CWG 1852 | C++14 | der auto Spezifizierer in decltype ( auto ) war ebenfalls ein Platzhalter |
kein Platzhalter
in diesem Fall |
| CWG 1892 | C++11 | der Rückgabetyp eines Funktionszeiger-Typ-IDs konnte auto sein | verboten |
| CWG 2476 | C++11 |
die Lösung von
CWG Issue 1892
verbot die Ableitung
des Rückgabetyps von Funktionszeiger-Variablen aus Initialisierern |
erlaubt |
| N3922 | C++11 | Direkt-List-Initialisierung von auto leitet std::initializer_list ab |
ungültig für mehr als ein
Element, leitet Elementtyp für einzelnes Element ab |
Referenzen
- C++23-Standard (ISO/IEC 14882:2024):
-
- 9.2.9.6 Platzhalter-Typspezifizierer [dcl.spec.auto]
- C++20-Standard (ISO/IEC 14882:2020):
-
- 9.2.8.5 Platzhalter-Typspezifizierer [dcl.spec.auto]
- C++17-Standard (ISO/IEC 14882:2017):
-
-
10.1.7.4 Der
auto-Spezifizierer [dcl.spec.auto]
-
10.1.7.4 Der
- C++14-Standard (ISO/IEC 14882:2014):
-
-
7.1.6.4
autoSpezifizierer [dcl.spec.auto]
-
7.1.6.4
- C++11-Standard (ISO/IEC 14882:2011):
-
-
7.1.6.4
autoSpezifizierer [dcl.spec.auto]
-
7.1.6.4