Konzepte-Bibliothek (seit C++20)
Die Konzepte-Bibliothek stellt Definitionen grundlegender Bibliothekskonzepte bereit, die zur Durchführung von Kompilierungszeitvalidierungen von Template-Argumenten und zur Funktionsauswahl basierend auf den Eigenschaften von Typen verwendet werden können. Diese Konzepte bilden die Grundlage für äquationsorientiertes Schließen in Programmen.
Die meisten Konzepte in der Standardbibliothek legen sowohl syntaktische als auch semantische Anforderungen fest. Es wird gesagt, dass ein Standardkonzept erfüllt ist, wenn seine syntaktischen Anforderungen erfüllt sind, und modelliert ist, wenn es erfüllt ist und seine semantischen Anforderungen (falls vorhanden) ebenfalls erfüllt sind.
Im Allgemeinen können nur die syntaktischen Anforderungen vom Compiler geprüft werden. Wenn die Gültigkeit oder Bedeutung eines Programms davon abhängt, ob eine Sequenz von Template-Argumenten ein Konzept modelliert, und das Konzept erfüllt, aber nicht modelliert ist, oder wenn eine semantische Anforderung an der Verwendungsstelle nicht erfüllt ist, ist das Programm schlecht geformt (ill-formed), keine Diagnose erforderlich.
Inhalt |
[bearbeiten] Gleichheitserhaltung
Ein Ausdruck ist gleichheitserhaltend, wenn er bei gleichen Eingaben gleiche Ausgaben liefert, wobei
- die Eingaben seine Operanden umfassen (nicht notwendigerweise macht dies den Ausdruck semantisch gültig), und
- die Ausgaben sein Ergebnis und alle durch den Ausdruck verursachten Änderungen an den Operanden umfassen, falls vorhanden.
wobei für eine bequemere Formulierung "Operanden" die größten Unterausdrücke bezeichnen, die aus einem id-Ausdruck oder Aufrufen von std::move, std::forward und std::declval bestehen.
Die cv-Qualifikation und die Wertkategorie jedes Operanden werden ermittelt, indem angenommen wird, dass jeder Template-Typ-Parameter in seinem Typ einen cv-unqualifizierten vollständigen Nicht-Array-Objekttyp bezeichnet.
Jeder Ausdruck, der gleichheitserhaltend sein muss, muss außerdem stabil sein, d.h. zwei Auswertungen desselben Ausdrucks mit denselben Eingabeobjekten müssen gleiche Ausgaben liefern, ohne dass eine explizite Änderung dieser Eingabeobjekte dazwischenliegt.
Sofern nicht anders angegeben, muss jeder Ausdruck, der in einem requires Ausdruck der Standardbibliothekskonzepte verwendet wird, gleichheitserhaltend sein, und die Auswertung des Ausdrucks darf nur seine nicht-konstanten Operanden ändern. Konstante Operanden dürfen nicht geändert werden.
In der Standardbibliothek dürfen die folgenden Konzepte nicht gleichheitserhaltende requires Ausdrücke haben:
[bearbeiten] Implizite Ausdrucksvariationen
Ein requires Ausdruck, der einen Ausdruck verwendet, der für einen bestimmten konstanten lvalue-Operanden nicht modifizierend ist, impliziert zusätzlich weitere Variationen dieses Ausdrucks, die einen nicht-konstanten lvalue oder einen (möglicherweise konstanten) rvalue für den gegebenen Operanden akzeptieren, es sei denn, eine solche Ausdrucks-Variation wird explizit mit abweichenden Semantiken gefordert.
Diese impliziten Ausdrucksvariationen müssen die gleichen semantischen Anforderungen des deklarierten Ausdrucks erfüllen. Das Ausmaß, in dem eine Implementierung die Syntax der Variationen überprüft, ist nicht spezifiziert.
template<class T> concept C = requires(T a, T b, const T c, const T d) { c == d; // expression #1: does not modify the operands a = std::move(b); // expression #2: modifies both operands a = c; // expression #3: modifies the left operand `a` }; // Expression #1 implicitly requires additional expression variations that // meet the requirements for c == d (including non-modification), // as if the following expressions had been declared as well: // ------ const == const ------- ------ const == non-const --- // c == b; // c == std::move(d); c == std::move(b); // std::move(c) == d; std::move(c) == b; // std::move(c) == std::move(d); std::move(c) == std::move(b); // -- non-const == const ------- -- non-const == non-const --- // a == d; a == b; // a == std::move(d); a == std::move(b); // std::move(a) == d; std::move(a) == b; // std::move(a) == std::move(d); std::move(a) == std::move(b); // Expression #3 implicitly requires additional expression variations that // meet the requirements for a = c // (including non-modification of the second operand), // as if the expressions a = b (non-constant lvalue variation) // and a = std::move(c) (const rvalue variation) had been declared. // Note: Since expression #2 already requires the non-constant rvalue variation // (a == std::move(b)) explicitly, expression #3 does not implicitly require it anymore. // The type T meets the explicitly stated syntactic requirements of // concept C above, but does not meet the additional implicit requirements // (i.e., T satisfies but does not model C): // a program requires C<T> is ill-formed (no diagnostic required). struct T { bool operator==(const T&) const { return true; } bool operator==(T&) = delete; };
[bearbeiten] Standardbibliothekskonzepte
| Definiert im Namespace
std | |
Kernsprachen-Konzepte | |
| Definiert in der Header-Datei
<concepts> | |
| (C++20) |
gibt an, dass ein Typ identisch mit einem anderen Typ ist (Konzept) |
| (C++20) |
gibt an, dass ein Typ von einem anderen Typ abgeleitet ist (Konzept) |
| (C++20) |
gibt an, dass ein Typ implizit in einen anderen Typ konvertierbar ist (Konzept) |
| (C++20) |
gibt an, dass zwei Typen einen gemeinsamen Referenztyp haben (Konzept) |
| (C++20) |
gibt an, dass zwei Typen einen gemeinsamen Typ haben (Konzept) |
| (C++20) |
gibt an, dass ein Typ ein ganzzahliger Typ ist (Konzept) |
| (C++20) |
gibt an, dass ein Typ ein vorzeichenbehafteter ganzzahliger Typ ist (Konzept) |
| (C++20) |
gibt an, dass ein Typ ein vorzeichenloser ganzzahliger Typ ist (Konzept) |
| (C++20) |
gibt an, dass ein Typ ein Fließkommatyp ist (Konzept) |
| (C++20) |
gibt an, dass ein Typ von einem anderen Typ zuweisbar ist (Konzept) |
| (C++20) |
gibt an, dass ein Typ vertauscht werden kann oder dass zwei Typen miteinander vertauscht werden können (Konzept) |
| (C++20) |
spezifiziert, dass ein Objekt des Typs zerstört werden kann (Konzept) |
| (C++20) |
gibt an, dass eine Variable des Typs aus einer Reihe von Argumenttypen konstruiert oder an sie gebunden werden kann (Konzept) |
| (C++20) |
gibt an, dass ein Objekt eines Typs standardkonstruiert werden kann (Konzept) |
| (C++20) |
gibt an, dass ein Objekt eines Typs per Move konstruiert werden kann (Konzept) |
| (C++20) |
gibt an, dass ein Objekt eines Typs kopierkonstruiert und per Move konstruiert werden kann (Konzept) |
Vergleichskonzepte | |
| Definiert in der Header-Datei
<concepts> | |
| (C++20) |
gibt an, dass ein Typ in booleschen Kontexten verwendet werden kann (Exposition-only Konzept*) |
| gibt an, dass der Operator == eine Äquivalenzrelation ist (Konzept) | |
| gibt an, dass die Vergleichsoperatoren des Typs eine Totalordnung ergeben (Konzept) | |
| Definiert in der Header-Datei
<compare> | |
| gibt an, dass der Operator <=> konsistente Ergebnisse für die gegebenen Typen liefert (Konzept) | |
Objektkonzepte | |
| Definiert in der Header-Datei
<concepts> | |
| (C++20) |
gibt an, dass ein Objekt eines Typs verschoben und vertauscht werden kann (Konzept) |
| (C++20) |
gibt an, dass ein Objekt eines Typs kopiert, verschoben und vertauscht werden kann (Konzept) |
| (C++20) |
gibt an, dass ein Objekt eines Typs kopiert, verschoben, vertauscht und standardkonstruiert werden kann (Konzept) |
| (C++20) |
gibt an, dass ein Typ regulär ist, d.h. er ist sowohl semiregular als auch equality_comparable(Konzept) |
Aufrufbare Konzepte | |
| Definiert in der Header-Datei
<concepts> | |
| (C++20) |
gibt an, dass ein aufrufbarer Typ mit einem gegebenen Satz von Argumenttypen aufgerufen werden kann (Konzept) |
| (C++20) |
gibt an, dass ein aufrufbarer Typ ein boolesches Prädikat ist (Konzept) |
| (C++20) |
gibt an, dass ein aufrufbarer Typ eine binäre Relation ist (Konzept) |
| (C++20) |
gibt an, dass eine Relation eine Äquivalenzrelation darstellt(Konzept) |
| (C++20) |
gibt an, dass eine Relation eine strikt schwache Ordnung darstellt(Konzept) |
Zusätzliche Konzepte finden Sie in der Iteratoren-Bibliothek, der Algorithmen-Bibliothek und der Ranges-Bibliothek.