Attribut-Spezifizierer-Sequenz (seit C++11)
Führt implementierungsdefinierte Attribute für Typen, Objekte, Code usw. ein.
Inhalt |
[bearbeiten] Syntax
[[ attributliste ]] |
(seit C++11) | ||||||||
[[ using attribut-namespace : attributliste ]] |
(seit C++17) | ||||||||
wobei attributliste eine durch Kommata getrennte Sequenz von null oder mehr attributen ist (die möglicherweise mit einer Auslassung ... endet, was eine Pack-Erweiterung anzeigt)
| identifier | (1) | ||||||||
attribut-namespace :: identifikator |
(2) | ||||||||
identifikator ( argumentliste (optional) ) |
(3) | ||||||||
attribut-namespace :: identifikator ( argumentliste (optional) ) |
(4) | ||||||||
wobei attribut-namespace ein identifikator ist und argumentliste eine Sequenz von Tokens ist, bei der Klammern, eckige Klammern und geschweifte Klammern ausgeglichen sind (ausgeglichene-token-sequenz).
|
Wenn [[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]] [[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute |
(seit C++17) |
[bearbeiten] Erklärung
Attribute bieten die einheitliche Standard-Syntax für implementierungsdefinierte Spracherweiterungen, wie z. B. die GNU- und IBM-Spracherweiterungen __attribute__((...)), die Microsoft-Erweiterung __declspec() usw.
Ein Attribut kann fast überall im C++-Programm verwendet und auf fast alles angewendet werden: auf Typen, Variablen, Funktionen, Namen, Codeblöcke, ganze Übersetzungseinheiten, obwohl jedes spezifische Attribut nur dort gültig ist, wo es von der Implementierung zugelassen wird: [[expect_true]] könnte ein Attribut sein, das nur mit einem if verwendet werden kann und nicht mit einer Klassendeklaration. [[omp::parallel()]] könnte ein Attribut sein, das für einen Codeblock oder eine for-Schleife gilt, aber nicht für den Typ int usw. (beachten Sie, dass diese beiden Attribute fiktive Beispiele sind, siehe unten für die Standard- und einige Nicht-Standard-Attribute).
In Deklarationen können Attribute sowohl vor der gesamten Deklaration als auch direkt nach dem Namen der deklarierten Entität erscheinen, in welchem Fall sie kombiniert werden. In den meisten anderen Situationen gelten Attribute für die unmittelbar vorangehende Entität.
Der alignas-Spezifizierer ist Teil der Attribut-Spezifizierer-Sequenz, obwohl er eine andere Syntax hat. Er kann dort erscheinen, wo die [[...]]-Attribute erscheinen, und kann mit ihnen vermischt werden (vorausgesetzt, er wird dort verwendet, wo alignas zulässig ist).
Zwei aufeinanderfolgende linke eckige Klammer-Tokens ([[) dürfen nur beim Einführen eines Attribut-Spezifizierers oder innerhalb eines Attributarguments erscheinen.
void f() { int y[3]; y[[] { return 0; }()] = 1; // error int i [[cats::meow([[]])]]; // OK }
Zusätzlich zu den unten aufgeführten Standardattributen können Implementierungen beliebige nicht-standardmäßige Attribute mit implementierungsdefinierten Verhaltensweisen unterstützen. Alle von einer Implementierung unbekannten Attribute werden ignoriert, ohne einen Fehler zu verursachen.(seit C++17)
|
Ein Attribut ohne attribut-namespace und ein attribut-namespace, dessen Name entweder |
(seit C++20) |
[bearbeiten] Standardattribute
Die folgenden Attribute sind im C++-Standard definiert.
Standardattribute können nicht syntaktisch ignoriert werden: sie dürfen keine Syntaxfehler enthalten, müssen auf das korrekte Ziel angewendet werden, und Entitäten in den Argumenten müssen ODR-used sein.
Standardattribute können auch semantisch nicht ignoriert werden: das Verhalten bei Entfernung aller Instanzen eines bestimmten Standardattributs wäre ein konformes Verhalten für das ursprüngliche Programm mit dem vorhandenen Attribut.
[[noreturn]](C++11) |
zeigt an, dass die Funktion nicht zurückkehrt (Attribut-Spezifizierer) |
| (C++11)(entfernt in C++26) |
zeigt an, dass die Abhängigkeitskette in Release-Consume std::memory_order in die und aus der Funktion propagiert (Attribut-Spezifizierer) |
[[deprecated]][[deprecated("Grund")]](C++14)(C++14) |
zeigt an, dass die Verwendung des Namens oder der Entität, die mit diesem Attribut deklariert wurde, erlaubt, aber aus einem bestimmten Grund nicht empfohlen wird (Attribut-Spezifizierer) |
[[fallthrough]](C++17) |
zeigt an, dass der Fall-Through vom vorherigen Case-Label beabsichtigt ist und von einem Compiler, der Fall-Through warnt, nicht diagnostiziert werden sollte (Attribut-Spezifizierer) |
[[maybe_unused]](C++17) |
unterdrückt Compiler-Warnungen bei unbenutzten Entitäten, falls vorhanden (Attribut-Spezifizierer) |
| fordert den Compiler auf, eine Warnung auszugeben, wenn der Rückgabewert verworfen wird (Attribut-Spezifizierer) | |
| zeigt an, dass der Compiler für den Fall optimieren sollte, dass ein Ausführungspfad durch eine Anweisung wahrscheinlicher oder unwahrscheinlicher ist als jeder andere Ausführungspfad (Attribut-Spezifizierer) | |
| (C++20) |
zeigt an, dass ein nicht-statisches Datenelement keine Adresse haben muss, die sich von allen anderen nicht-statischen Datenelementen seiner Klasse unterscheidet (Attribut-Spezifizierer) |
[[assume(ausdruck)]](C++23) |
spezifiziert, dass der ausdruck an einer gegebenen Stelle immer zu true ausgewertet wird (Attribut-Spezifizierer) |
[[indeterminate]](C++26) |
spezifiziert, dass ein Objekt einen unbestimmten Wert hat, wenn es nicht initialisiert wird (Attribut-Spezifizierer) |
| (TM TS) |
zeigt an, dass die Funktionsdefinition für die Aufrufe aus einer synchronized-Anweisung optimiert werden sollte (Attribut-Spezifizierer) |
[bearbeiten] Hinweise
Die Anwesenheit jedes einzelnen Attributs auf einer bestimmten Plattform kann mit dem Präprozessor-Makro __has_cpp_attribute überprüft werden.
| Feature-Testmakro | Wert | Std | Feature |
|---|---|---|---|
__cpp_attributes |
200809L |
(C++11) | Attribute |
__cpp_namespace_attributes |
201411L |
(C++17) | Attribute für Namespaces |
[bearbeiten] Beispiel
[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]] inline int f(); // declare f with four attributes [[gnu::always_inline, gnu::const, gnu::hot, nodiscard]] int f(); // same as above, but uses a single attr specifier that contains four attributes // C++17: [[using gnu : const, always_inline, hot]] [[nodiscard]] int f[[gnu::always_inline]](); // an attribute may appear in multiple specifiers int f() { return 0; } int main() {}
[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 2079 | C++11 | [[ konnte nicht innerhalb eines Attributarguments erscheinen |
erlaubt |
| CWG 2538 | C++11 | es war unklar, ob Standardattribute syntaktisch ignoriert werden können | verboten |
| CWG 2695 | C++11 | es war unklar, ob Standardattribute semantisch ignoriert werden können | verboten |
| P2156R1 | C++11 | jedes Standardattribut musste höchstens einmal in einer attributliste erscheinen | nicht erforderlich. |
[bearbeiten] Siehe auch
__has_cpp_attribute - prüft auf das Vorhandensein eines Attributs | |
| C-Dokumentation für Attribut-Spezifizierer-Sequenz
|
[bearbeiten] Externe Links
| 1. | Attribute in GCC. Diese Attribute können als [[gnu::...]] verwendet werden, Siehe SO. |
| 2. | Attribute in Clang. |
| 3. | Attribute in MSVC. |