Konstante Ausdrücke
Definiert einen Ausdruck, der zur Kompilierzeit ausgewertet werden kann.
Solche Ausdrücke können als Nicht-Typ-Template-Argumente, Array-Größen und in anderen Kontexten verwendet werden, die konstante Ausdrücke erfordern, z. B.
int n = 1; std::array<int, n> a1; // Error: “n” is not a constant expression const int cn = 2; std::array<int, cn> a2; // OK: “cn” is a constant expression
[bearbeiten] Definition
|
Ein Ausdruck, der zu einer der unten aufgeführten Kategorien von konstanten Ausdrücken gehört, ist ein konstanter Ausdruck.
|
(bis C++11) | ||
|
Die folgenden Ausdrücke werden kollektiv als konstante Ausdrücke bezeichnet
|
(seit C++11) (bis C++14) | ||
|
Die folgenden Entitäten sind erlaubte Ergebnisse eines konstanten Ausdrucks
Ein konstanter Ausdruck ist entweder ein glvalue Kern-Konstanter Ausdruck, der auf eine Entität verweist, die ein erlaubtes Ergebnis eines konstanten Ausdrucks ist, oder ein prvalue Kern-Konstanter Ausdruck, dessen Wert die folgenden Einschränkungen erfüllt
|
(seit C++14) (bis C++26) | ||
|
Ein konstanter Ausdruck ist entweder ein glvalue Kern-Konstanter Ausdruck, der auf ein Objekt oder eine nicht-sofortige Funktion verweist, oder ein prvalue Kern-Konstanter Ausdruck, dessen Wert die folgenden Einschränkungen erfüllt
|
(seit C++26) |
Bei der Bestimmung, ob ein Ausdruck ein konstanter Ausdruck ist, wird angenommen, dass Copy Elision nicht durchgeführt wird.
Die C++98-Definition von konstanten Ausdrücken befindet sich vollständig in der Kollapsbox. Die folgende Beschreibung gilt für C++11 und spätere C++-Versionen.
[bearbeiten] Literal-Typ
Die folgenden Typen werden kollektiv als Literal-Typen bezeichnet
- möglicherweise cv-qualifiziertes void
- Skalar-Typ
- Referenz-Typ
- ein Array vom Literal-Typ
- möglicherweise cv-qualifizierter Klassentyp, der alle folgenden Bedingungen erfüllt
- Er hat einen trivialen Destruktor(bis C++20)constexpr Destruktor(seit C++20).
- Alle seine nicht-statischen Nicht-Varianten-Datenmember und Basisklassen sind von nicht-volatilen Literal-Typen.
- Er ist einer der folgenden Typen
|
(seit C++17) |
- ein Aggregat-Union-Typ, der eine der folgenden Bedingungen erfüllt
- Er hat kein Varianten-Member.
- Er hat mindestens ein Varianten-Member vom nicht-volatilen Literal-Typ.
- ein nicht-Union-Aggregat-Typ, und jeder seiner anonymen Union-Member erfüllt eine der folgenden Bedingungen
- Er hat kein Varianten-Member.
- Er hat mindestens ein Varianten-Member vom nicht-volatilen Literal-Typ.
- ein Typ mit mindestens einem constexpr-Konstruktor (Template), der kein Kopier- oder Verschiebekonstruktor ist
Nur Objekte von Literal-Typen können innerhalb eines konstanten Ausdrucks erstellt werden.
[bearbeiten] Kern-Konstantausdruck
Ein Kern-Konstanter Ausdruck ist jeder Ausdruck, dessen Auswertung **nicht** einen der folgenden Sprachkonstrukte auswertet
| Sprachkonstrukt | Version | Papier(e) |
|---|---|---|
der this-Zeiger, außer in einer constexpr Funktion, die als Teil des Ausdrucks ausgewertet wird, oder wenn er in einem impliziten oder expliziten Klassenmember-Zugriffs-Ausdruck vorkommt |
N2235 | |
| ein Kontrollfluss, der durch eine Deklaration einer Blockvariable mit statischer oder Thread- Speicher-Dauer führt, die nicht in konstanten Ausdrücken verwendbar ist | (seit C++23) | P2242R3 |
| Dieser Abschnitt ist unvollständig Grund: Übertragen Sie den Inhalt aus der unten stehenden rohen HTML-geordneten Liste in die obige Wiki-Tabelle und fügen Sie die Papiere/CWG-Probleme hinzu, die den entsprechenden Eintrag im Standard eingeführt haben. Die Mini-Beispiele werden nicht beibehalten, sie können am Ende dieser Seite zu einem großen Beispiel zusammengefasst werden. |
- ein Funktionsaufrufausdruck, der eine Funktion (oder einen Konstruktor) aufruft, die/der nicht als constexpr deklariert ist
constexpr int n = std::numeric_limits<int>::max(); // OK: max() is constexpr constexpr int m = std::time(nullptr); // Error: std::time() is not constexpr
- ein Funktionsaufruf an eine constexpr-Funktion, die deklariert, aber nicht definiert ist
- ein Funktionsaufruf an eine constexpr-Funktion/Konstruktor-Template-Instanziierung, bei der die Instanziierung die Anforderungen an eine constexpr Funktion/Konstruktor nicht erfüllt.
- ein Funktionsaufruf einer konstanten virtuellen Funktion, aufgerufen für ein Objekt, dessen dynamischer Typ constexpr-unbekannt ist
- ein Ausdruck, der die implementierungsdefinierten Grenzen überschreiten würde
- ein Ausdruck, dessen Auswertung zu irgendeiner Form von undefiniertem oder fehlerhaftem(seit C++26) Verhalten der Kernsprache führt, außer für jegliches potenzielle undefinierte Verhalten, das durch Standardattribute eingeführt wird.
constexpr double d1 = 2.0 / 1.0; // OK constexpr double d2 = 2.0 / 0.0; // Error: not defined constexpr int n = std::numeric_limits<int>::max() + 1; // Error: overflow int x, y, z[30]; constexpr auto e1 = &y - &x; // Error: undefined constexpr auto e2 = &z[20] - &z[3]; // OK constexpr std::bitset<2> a; constexpr bool b = a[2]; // UB, but unspecified if detected
- (bis C++17) ein Lambda-Ausdruck
- eine implizite Konvertierung von lvalue zu rvalue, es sei denn, sie wird angewendet auf...
- ein glvalue vom Typ (möglicherweise cv-qualifiziert) std::nullptr_t
- ein nicht-volatiles glvalue vom Literal-Typ, der ein Objekt bezeichnet, das in konstanten Ausdrücken verwendbar ist
int main() { const std::size_t tabsize = 50; int tab[tabsize]; // OK: tabsize is a constant expression // because tabsize is usable in constant expressions // because it has const-qualified integral type, and // its initializer is a constant initializer std::size_t n = 50; const std::size_t sz = n; int tab2[sz]; // Error: sz is not a constant expression // because sz is not usable in constant expressions // because its initializer was not a constant initializer }
- ein nicht-volatiles glvalue vom Literal-Typ, der auf ein nicht-volatiles Objekt verweist, dessen Lebensdauer innerhalb der Auswertung dieses Ausdrucks begann
- eine implizite Konvertierung von lvalue zu rvalue oder eine Modifikation, die auf einen nicht-aktiven Member einer Union oder sein Teilobjekt angewendet wird (auch wenn er eine gemeinsame Anfangssequenz mit dem aktiven Member teilt)
- eine implizite Konvertierung von lvalue zu rvalue für ein Objekt, dessen Wert unbestimmt ist
- ein Aufruf des impliziten Kopier-/Verschiebekonstruktors/-zuweisungsoperators für eine Union, deren aktiver Member veränderlich ist (falls vorhanden), wobei die Lebensdauer außerhalb der Auswertung dieses Ausdrucks beginnt
- (bis C++20) ein Zuweisungsausdruck, der den aktiven Member einer Union ändern würde
- Konvertierung von Zeiger auf void zu einem Zeiger-auf-Objekt-Typ
T*es sei denn, der Zeiger enthält einen Nullzeigerwert oder zeigt auf ein Objekt, dessen Typ ähnlich zuTist(seit C++26) -
dynamic_castdessen Operand ein glvalue ist, das auf ein Objekt verweist, dessen dynamischer Typ constexpr-unbekannt ist(seit C++20) -
reinterpret_cast - (bis C++20) Pseudo-Destruktoraufruf
- (bis C++14) ein Inkrementierungs- oder Dekrementierungsoperator
-
(seit C++14) Modifikation eines Objekts, es sei denn, das Objekt hat einen nicht-volatilen Literal-Typ und seine Lebensdauer begann innerhalb der Auswertung des Ausdrucks
constexpr int incr(int& n) { return ++n; } constexpr int g(int k) { constexpr int x = incr(k); // Error: incr(k) is not a core constant // expression because lifetime of k // began outside the expression incr(k) return x; } constexpr int h(int k) { int x = incr(k); // OK: x is not required to be initialized // with a core constant expression return x; } constexpr int y = h(1); // OK: initializes y with the value 2 // h(1) is a core constant expression because // the lifetime of k begins inside the expression h(1)
- (seit C++20) ein Destruktoraufruf oder Pseudo-Destruktoraufruf für ein Objekt, dessen Lebensdauer nicht innerhalb der Auswertung dieses Ausdrucks begann
- ein
typeid-Ausdruck, angewendet auf ein glvalue vom polymorphen Typ und dieses glvalue verweist auf ein Objekt, dessen dynamischer Typ constexpr-unbekannt ist(seit C++20) - ein new-Ausdruck, es sei denn, eine der folgenden Bedingungen ist erfüllt:(seit C++20)
- Die ausgewählte Allocationsfunktion ist eine ersetzbare globale Allocationsfunktion und der zugewiesene Speicher wird innerhalb der Auswertung dieses Ausdrucks freigegeben.
(seit C++20) - Die ausgewählte Allocationsfunktion ist eine nicht-allozierende Form mit einem zugewiesenen Typ
T, und das Platzierungsargument erfüllt alle folgenden Bedingungen
- Es verweist auf
- ein Objekt, dessen Typ ähnlich zu
Tist, wennTkein Array-Typ ist, oder - das erste Element eines Objekts eines zu
Tähnlichen Typs, wennTein Array-Typ ist.
- ein Objekt, dessen Typ ähnlich zu
- Es verweist auf Speicher, dessen Lebensdauer innerhalb der Auswertung dieses Ausdrucks begann.
(seit C++26) - ein delete-Ausdruck, es sei denn, er gibt einen Speicherbereich frei, der innerhalb der Auswertung dieses Ausdrucks zugewiesen wurde(seit C++20)
- (seit C++20) Coroutinen: ein await-Ausdruck oder ein yield-Ausdruck
- (seit C++20) ein Drei-Wege-Vergleich, wenn das Ergebnis nicht spezifiziert ist
- ein Gleichheits- oder Vergleichsoperator, dessen Ergebnis nicht spezifiziert ist
- (bis C++14) ein Zuweisungs- oder zusammengesetzter Zuweisungsoperator
- (bis C++26) ein throw-Ausdruck
- (seit C++26) eine Konstruktion eines Ausnahmeobjekts, es sei denn, das Ausnahmeobjekt und alle seine impliziten Kopien, die durch Aufrufe von std::current_exception oder std::rethrow_exception erstellt wurden, werden innerhalb der Auswertung dieses Ausdrucks zerstört
constexpr void check(int i) { if (i < 0) throw i; } constexpr bool is_ok(int i) { try { check(i); } catch (...) { return false; } return true; } constexpr bool always_throw() { throw 12; return true; } static_assert(is_ok(5)); // OK static_assert(!is_ok(-1)); // OK since C++26 static_assert(always_throw()); // Error: uncaught exception
- eine asm-Deklaration
- ein Aufruf des Makros va_arg
- eine
goto-Anweisung - ein
dynamic_cast- odertypeid-Ausdruck oder new-Ausdruck(seit C++26), der eine Ausnahme auslösen würde wenn keine Definition des Ausnahmetyps erreichbar ist(seit C++26) - innerhalb eines Lambda-Ausdrucks eine Referenz auf this oder auf eine außerhalb dieses Lambda definierten Variable, wenn diese Referenz eine ODR-Nutzung wäre
void g() { const int n = 0; constexpr int j = *&n; // OK: outside of a lambda-expression [=] { constexpr int i = n; // OK: 'n' is not odr-used and not captured here. constexpr int j = *&n; // Ill-formed: '&n' would be an odr-use of 'n'. }; }
beachten Sie, dass, wenn die ODR-Nutzung in einem Funktionsaufruf einer Closure stattfindet, sie sich nicht auf this oder eine umschließende Variable bezieht, da sie stattdessen auf ein Datenmember der Closure zugreift
// OK: 'v' & 'm' are odr-used but do not occur in a constant-expression // within the nested lambda auto monad = [](auto v){ return [=]{ return v; }; }; auto bind = [](auto m){ return [=](auto fvm){ return fvm(m()); }; }; // OK to have captures to automatic objects created during constant expression evaluation. static_assert(bind(monad(2))(monad)() == monad(2)());
(seit C++17)
[bearbeiten] Zusätzliche Anforderungen
Auch wenn ein Ausdruck E nichts von dem oben Genannten auswertet, ist es implementierungsabhängig, ob E ein Kern-Konstanter Ausdruck ist, wenn die Auswertung von E zu laufzeit-undefiniertem Verhalten führen würde.
Auch wenn ein Ausdruck E nichts von dem oben Genannten auswertet, ist es unspezifiziert, ob E ein Kern-Konstanter Ausdruck ist, wenn die Auswertung von E eines der folgenden Elemente auswertet
- Eine Operation mit undefiniertem Verhalten in der Standardbibliothek.
- Ein Aufruf des Makros va_start.
Für die Zwecke der Bestimmung, ob ein Ausdruck ein Kern-Konstanter Ausdruck ist, wird die Auswertung des Körpers einer Member-Funktion von std::allocator<T> ignoriert, wenn T ein Literal-Typ ist.
Für die Zwecke der Bestimmung, ob ein Ausdruck ein Kern-Konstanter Ausdruck ist, wird die Auswertung eines Aufrufs eines trivialen Kopier-/Verschiebekonstruktors oder Kopier-/Zuweisungsoperators einer Union als Kopieren/Verschieben des aktiven Members der Union betrachtet, falls vorhanden.
|
Für die Zwecke der Bestimmung, ob ein Ausdruck ein Kern-Konstanter Ausdruck ist, hat die Auswertung eines Bezeichnerausdrucks, der ein strukturiertes Binding bd bezeichnet, die folgenden Semantiken
|
(seit C++26) |
Während der Auswertung des Ausdrucks als Kern-Konstanter Ausdruck werden alle Bezeichnerausdrücke und Verwendungen von *this, die auf ein Objekt oder eine Referenz verweisen, deren Lebensdauer außerhalb der Auswertung des Ausdrucks begann, so behandelt, als würden sie auf eine spezifische Instanz dieses Objekts oder dieser Referenz verweisen, deren Lebensdauer und die aller Teilobjekte (einschließlich aller Union-Member) die gesamte konstante Auswertung umfasst.
- Für ein solches Objekt das nicht in konstanten Ausdrücken verwendbar ist(seit C++20) ist der dynamische Typ des Objekts constexpr-unbekannt.
- Für eine solche Referenz die nicht in konstanten Ausdrücken verwendbar ist(seit C++20) wird die Referenz so behandelt, als wäre sie an ein unspezifiziertes Objekt des Referenztyps gebunden, dessen Lebensdauer und die aller Teilobjekte die gesamte konstante Auswertung umfasst und dessen dynamischer Typ constexpr-unbekannt ist.
[bearbeiten] Ganzzahliger konstanter Ausdruck
Ganzzahliger konstanter Ausdruck ist ein Ausdruck vom ganzzahligen oder nicht-gesteckten Aufzählungstyp, der implizit in einen prvalue konvertiert wird, wobei der konvertierte Ausdruck ein Kern-Konstanter Ausdruck ist.
Wenn ein Ausdruck vom Klassentyp dort verwendet wird, wo ein ganzzahliger konstanter Ausdruck erwartet wird, wird der Ausdruck kontextuell implizit in einen ganzzahligen oder nicht-gesteckten Aufzählungstyp konvertiert.
[bearbeiten] Konvertierter konstanter Ausdruck
Ein konvertierter konstanter Ausdruck vom Typ T ist ein Ausdruck, der implizit in den Typ T konvertiert wird, wobei der konvertierte Ausdruck ein konstanter Ausdruck ist und die implizite Konvertierungssequenz nur Folgendes enthält
- constexpr benutzerdefinierte Konvertierungen
- lvalue-zu-rvalue-Konvertierungen
- Ganzzahlige Promotionen
- nicht-verengende Ganzzahlkonvertierungen
- Gleitkomma-Promotionen
- nicht-verengende Gleitkommakonvertierungen
| (seit C++17) |
Und wenn eine Referenzbindung stattfindet, kann sie nur eine direkte Bindung sein.
Die folgenden Kontexte erfordern einen konvertierten konstanten Ausdruck
- der constant_expression von case-Labels
- Aufzählungskonstantenelemente-Initialisierer, wenn der zugrunde liegende Typ festgelegt ist
- ganzzahlige und Aufzählungs-(bis C++17)Nicht-Typ- Template-Argumente
|
(seit C++14) |
|
(seit C++26) |
Ein kontextuell konvertierter konstanter Ausdruck vom Typ bool ist ein Ausdruck, der kontextuell in bool konvertiert wird, wobei der konvertierte Ausdruck ein konstanter Ausdruck ist und die Konvertierungssequenz nur die oben genannten Konvertierungen enthält.
Die folgenden Kontexte erfordern einen kontextuell konvertierten konstanten Ausdruck vom Typ bool
| (bis C++23) | |
| (seit C++17) (bis C++23) | |
| (seit C++20) |
BestandteileDie Bestandteil-Werte eines Objekts obj werden wie folgt definiert
Die Bestandteil-Referenzen eines Objekts obj umfassen die folgenden Referenzen
Die Bestandteil-Werte und Bestandteil-Referenzen einer Variablen var werden wie folgt definiert
Für jede Bestandteilreferenz ref einer Variablen var, falls ref an ein temporäres Objekt oder ein Teilobjekt davon gebunden ist, dessen Lebensdauer bis zu der von ref verlängert wird, sind die Bestandteilwerte und -referenzen dieses temporären Objekts rekursiv ebenfalls Bestandteilwerte und -referenzen von var. Constexpr-darstellbare EntitätenObjekte mit statischer Speicherungsdauer sind zu jedem Zeitpunkt im Programm constexpr-referenzierbar. Ein Objekt obj mit automatischer Speicherungsdauer ist von einem Punkt Ein Objekt oder eine Referenz x ist an einem Punkt
|
(seit C++26) | ||||||||
Konstant-initialisierte Entitäten
Verwendbar in konstanten AusdrückenEine Variable ist potenziell konstant, wenn sie eine constexpr-Variable ist oder einen Referenz- oder nicht-flüchtigen, const-qualifizierten ganzzahligen oder Enumerationstyp hat. Eine konstant-initialisierte, potenziell konstante Variable var ist an einem Punkt
Manifest eindeutig konstant ausgewertete AusdrückeDie folgenden Ausdrücke (einschließlich Konvertierungen zum Zieltyp) sind manifest eindeutig konstant ausgewertet
Ob eine Auswertung in einem manifest eindeutig konstant ausgewerteten Kontext stattfindet, kann mit std::is_constant_evaluated und |
(seit C++20) |
[edit] Funktionen und Variablen für die konstante Auswertung erforderlich
Folgende Ausdrücke oder Konvertierungen sind potenziell konstant ausgewertet
- manifest eindeutig konstant ausgewertete Ausdrücke
- potenziell ausgewertete Ausdrücke
- unmittelbare Teilausdrücke einer geschweiften Initialisierungsliste (eine konstante Auswertung kann notwendig sein, um zu bestimmen, ob eine Konvertierung einschränkend ist)
- Adress-von-Ausdrücke, die innerhalb einer Vorlagenentität auftreten (eine konstante Auswertung kann notwendig sein, um zu bestimmen, ob ein solcher Ausdruck wertabhängig ist)
- Teilausdrücke von einem der obigen, die kein Teilausdruck eines verschachtelten nicht ausgewerteten Operanden sind
Eine Funktion ist für die konstante Auswertung erforderlich, wenn sie eine constexpr-Funktion ist und von einem Ausdruck genannt wird, der potenziell konstant ausgewertet wird.
Eine Variable ist für die konstante Auswertung erforderlich, wenn sie entweder eine constexpr-Variable ist oder einen nicht-flüchtigen, const-qualifizierten ganzzahligen Typ oder einen Referenztyp hat und der Bezeichnerausdruck, der sie bezeichnet, potenziell konstant ausgewertet wird.
Die Definition einer abgeleiteten Funktion und die Instanziierung einer Funktionsvorlagenspezialisierung oder einer Variablentemplatespezialisierung(seit C++14) wird ausgelöst, wenn die Funktion oder Variable(seit C++14) für die konstante Auswertung erforderlich ist.
[edit] Konstanter Teilausdruck
Ein konstanter Teilausdruck ist ein Ausdruck, dessen Auswertung als Teilausdruck eines Ausdrucks e e nicht daran hindern würde, ein Kernkonstantenausdruck zu sein, wobei e keiner der folgenden Ausdrücke ist
| (seit C++20) |
[edit] Hinweise
| Feature-Testmakro | Wert | Std | Feature |
|---|---|---|---|
__cpp_constexpr_in_decltype |
201711L |
(C++20) (DR11) |
Generierung von Funktions- und Variablendefinitionen, wenn sie gemäß für die konstante Auswertung erforderlich sind |
__cpp_constexpr_dynamic_alloc |
201907L |
(C++20) | Operationen für dynamische Speicherverwaltung in constexpr-Funktionen |
__cpp_constexpr |
202306L |
(C++26) | constexpr-Cast von void*: Richtung Typ-Erasure |
202406L |
(C++26) | constexpr Placement new und new[] | |
__cpp_constexpr_exceptions |
202411L |
(C++26) | constexpr-Ausnahmen |
[edit] Beispiel
| Dieser Abschnitt ist unvollständig Grund: kein Beispiel |
[edit] 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 94 | C++98 | arithmetische konstante Ausdrücke konnten nicht Variablen und statische Datenmember involvieren |
sie können es |
| CWG 366 | C++98 | Ausdrücke, die String-Literale involvieren konnten integrale konstante Ausdrücke sein |
sie sind es nicht |
| CWG 457 | C++98 | Ausdrücke, die volatile Variablen involvieren konnten integrale konstante Ausdrücke sein |
sie sind es nicht |
| CWG 1293 | C++11 | es war unklar, ob String-Literale in konstanten Ausdrücken verwendbar sind |
sie sind verwendbar |
| CWG 1311 | C++11 | volatile lvalues konnten in konstanten Ausdrücken verwendet werden | verboten |
| CWG 1312 | C++11 | reinterpret_cast ist in konstanten Ausdrücken verboten, aber das Casting zu und von void* konnte den gleichen Effekt erzielen |
verbotene Konvertierungen von Typ cv void* zu einem Pointer-to-Object-Typ |
| CWG 1313 | C++11 | undefiniertes Verhalten war erlaubt; die gesamte Pointer-Subtraktion war verboten |
UB verboten; dasselbe Array Pointer-Subtraktion OK |
| CWG 1405 | C++11 | für Objekte, die in konstanten Ausdrücken verwendbar sind, waren ihre veränderlichen Teilobjekte ebenfalls verwendbar |
sie sind nicht verwendbar |
| CWG 1454 | C++11 | Weitergabe von Konstanten über constexpr-Funktionen mittels Referenzen war nicht erlaubt |
erlaubt |
| CWG 1455 | C++11 | konvertierte konstante Ausdrücke konnten nur prvalues sein | können lvalues sein |
| CWG 1456 | C++11 | ein Adress-Konstantenausdruck konnte nicht die Adresse eines Arrays über das Ende hinaus bezeichnen |
erlaubt |
| CWG 1535 | C++11 | ein typeid-Ausdruck, dessen Operand ein polymorphes Klassentyp ist, war kein Kernkonstantenausdruck selbst wenn keine Laufzeitprüfung beteiligt ist |
die Operandeneinschränkung ist auf glvalues von polymorphen Klassentypen beschränkt |
| CWG 1581 | C++11 | für die konstante Auswertung benötigte Funktionen mussten nicht definiert oder instanziiert werden |
Gefordert |
| CWG 1613 | C++11 | Kernkonstantenausdrücke konnten beliebige ODR-verwendete Referenzen innerhalb von Lambda-Ausdrücken auswerten |
einige Referenzen konnten nicht ausgewertet werden |
| CWG 1694 | C++11 | die Bindung des Wertes eines Temporärs an eine Referenz mit statischer Speicherungsdauer war ein konstanter Ausdruck |
sie ist kein Konstanter Ausdruck |
| CWG 1872 | C++11 | Kernkonstantenausdrücke konnten constexpr-Funktionsvorlageninstanziierungen aufrufen die die Anforderungen für constexpr-Funktionen nicht erfüllen |
solche Instanziierungen können nicht aufgerufen werden |
| CWG 1952 | C++11 | undefinierte Standardbibliotheksverhaltensweisen mussten diagnostiziert werden |
unklar, ob sie diagnostiziert werden |
| CWG 2022 | C++98 | die Bestimmung des konstanten Ausdrucks könnte davon abhängen, ob Copy-Elision durchgeführt wird |
angenommen, dass Copy-Elision immer durchgeführt wird |
| CWG 2126 | C++11 | konstant-initialisierte, lebensdauer-erweiterte temporäre Objekte von const- qualifizierten Literal-Typen waren nicht in konstanten Ausdrücken verwendbar |
verwendbar |
| CWG 2129 | C++11 | Ganzzahl-Literale waren keine konstanten Ausdrücke | sie sind |
| CWG 2167 | C++11 | Nicht-Mitglieds-Referenzen lokal zu einer Auswertung machten die Auswertung nicht-constexpr |
Nicht-Mitglieds- Referenzen erlaubt |
| CWG 2278 | C++98 | die Lösung von CWG-Problem 2022 war nicht implementierbar | angenommen, dass Copy-Elision wird nie durchgeführt |
| CWG 2299 | C++14 | es war unklar, ob Makros in <cstdarg> in der konstanten Auswertung verwendet werden können |
va_arg verboten,va_start unbestimmt |
| CWG 2400 | C++11 | das Aufrufen einer constexpr virtuellen Funktion für ein Objekt, das nicht verwendbar ist in konstanten Ausdrücken und dessen Lebensdauer außerhalb des Ausdrucks begann, der den Aufruf enthält, konnte ein konstanter Ausdruck sein Ausdruck, der den Aufruf enthält, könnte ein konstanter Ausdruck sein |
sie ist kein Konstanter Ausdruck |
| CWG 2490 | C++20 | (Pseudo-)Destruktoraufrufe hatten keine Beschränkungen in der konstanten Auswertung |
Beschränkung hinzugefügt |
| CWG 2552 | C++23 | bei der Auswertung eines Kernkonstantenausdrucks konnte der Kontrollfluss nicht durch die Deklaration einer Nicht-Block-Variable fließen |
es kann |
| CWG 2558 | C++11 | ein unbestimmter Wert konnte ein konstanter Ausdruck sein | kein konstanter Ausdruck |
| CWG 2647 | C++20 | Variablen vom Typ volatile-qualifiziert konnten potenziell konstant sein | sie sind es nicht |
| CWG 2763 | C++11 | die Verletzung von [[noreturn]] musste nichtwährend der konstanten Auswertung erkannt werden |
Gefordert |
| CWG 2851 | C++11 | konvertierte konstante Ausdrücke erlaubten keine Gleitkomma-Konvertierungen |
erlaubt nicht-einschränkende Gleitkomma-Konvertierungen |
| CWG 2907 | C++11 | Kernkonstantenausdrücke konnten keine lvalue-zu-rvalue-Konvertierungen auf std::nullptr_t glvalues anwenden |
kann solche anwenden Konvertierungen |
| CWG 2909 | C++20 | eine Variable ohne Initialisierer konnte nur konstant-initialisiert werden, wenn ihre Default-Initialisierung zu einer tatsächlichen Initialisierung führt |
kann nur konstant- initialisiert werden, wenn ihr Typ const-default-konstruierbar ist |
| CWG 2924 | C++11 C++23 |
es war unbestimmt, ob ein Ausdruck, der die Constraints von [[noreturn]] (C++11) oder[[assume]] (C++23) verletzt, ein Kernkonstantenausdruck ist |
sie ist implementierungsdefiniert |
| P2280R4 | C++11 | die Auswertung eines Ausdrucks, der einen Bezeichnerausdruck oder *this enthält, der sich auf ein Objekt oder eine Referenz bezieht, deren Lebensdauer außerhalb dieser Auswertung begonnen hat, ist kein konstanter Ausdruck |
es kann ein Konstanter Ausdruck |
[edit] Siehe auch
constexpr-Spezifizierer(C++11) |
gibt an, dass der Wert einer Variablen oder Funktion zur Kompilierzeit berechnet werden kann |
| (C++11)(in C++17 veraltet)(in C++20 entfernt) |
prüft, ob ein Typ ein Literal-Typ ist (Klassenvorlage) |
| C-Dokumentation für Konstante Ausdrücke
| |