Constant expressions
Definiert einen Ausdruck , der zur Kompilierzeit ausgewertet werden kann.
Solche Ausdrücke können als konstante 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; // Fehler: „n“ ist kein konstanter Ausdruck const int cn = 2; std::array<int, cn> a2; // OK: „cn“ ist ein konstanter Ausdruck
Definition
|
Ein Ausdruck, der zu einer der unten aufgeführten Kategorien für konstante Ausdrücke gehört, ist ein konstanter Ausdruck .
|
(bis C++11) | ||
|
Die folgenden Ausdrücke werden zusammen als konstante Ausdrücke bezeichnet:
|
(seit C++11)
(bis C++14) |
||
|
Folgende Entitäten sind zulässige Ergebnisse eines konstanten Ausdrucks :
Ein konstanter Ausdruck ist entweder ein glvalue core constant expression , der auf eine Entität verweist, die ein zulässiges Ergebnis eines konstanten Ausdrucks ist, oder ein prvalue core constant expression, dessen Wert die folgenden Einschränkungen erfüllt:
|
(since C++14)
(until C++26) |
||
|
Ein konstanter Ausdruck ist entweder ein Glvalue- Core-Konstantausdruck , der auf ein Objekt oder eine Nicht- Immediate-Funktion verweist, oder ein Prvalue-Core-Konstantausdruck, 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 Definition von konstanten Ausdrücken in C++98 befindet sich vollständig innerhalb der Ausklappbox. Die folgende Beschreibung gilt für C++11 und spätere C++-Versionen.
Literaltyp
Die folgenden Typen werden zusammenfassend als literal types bezeichnet:
- möglicherweise cv-qualifiziertes void
- Skalartyp
- Referenztyp
- ein Array von Literaltyp
- möglicherweise cv-qualifizierter Klassentyp, der alle folgenden Bedingungen erfüllt:
-
- Es besitzt einen trivialen Destruktor (bis C++20) constexpr Destruktor (seit C++20) .
- Alle seine nicht-statischen nicht-varianten Datenelemente und Basisklassen sind von nicht-flüchtigen Literaltypen.
- Es ist einer der folgenden Typen:
|
(seit C++17) |
-
-
- ein Aggregat -Union-Typ, der eine der folgenden Bedingungen erfüllt:
-
- Er hat kein Varianten-Mitglied .
- Er hat mindestens ein Varianten-Mitglied von nicht-flüchtigem Literaltyp.
- ein Nicht-Union-Aggregat-Typ, bei dem jedes seiner anonymen Union -Mitglieder eine der folgenden Bedingungen erfüllt:
-
- Es hat kein Varianten-Mitglied.
- Es hat mindestens ein Varianten-Mitglied von nicht-flüchtigem Literaltyp.
- ein Typ mit mindestens einem constexpr -Konstruktor (Template), der kein Kopier- oder Verschiebungskonstruktor ist
-
Nur Objekte von Literaltypen können innerhalb eines konstanten Ausdrucks erstellt werden.
Kernkonstanter Ausdruck
Ein Kernkonstanter Ausdruck ist jeder Ausdruck, dessen Auswertung nicht eine der folgenden Sprachkonstrukte auswerten würde:
| Sprachkonstrukt | Version | Paper(s) |
|---|---|---|
der
this
Zeiger, außer in einer
constexpr
Funktion
die als Teil des Ausdrucks ausgewertet wird, oder wenn er in einem impliziten oder expliziten Klassenmitglied-Zugriffsausdruck erscheint
|
N2235 | |
| ein Kontrollfluss, der durch eine Deklaration einer Block-Variable mit static oder thread Speicherdauer verläuft, die nicht in konstanten Ausdrücken verwendbar ist | (since C++23) | P2242R3 |
|
Dieser Abschnitt ist unvollständig
Grund: Übertragen Sie die Inhalte aus der untenstehenden Roh-HTML-aufgezählten Liste in die obige Wikitabelle, während Sie die Papiere/CWG-Issues hinzufügen, die den entsprechenden Punkt in den Standard eingeführt haben. Die Mini-Beispiele werden nicht beibehalten, sie können zu einem großen Beispiel am Ende dieser Seite kombiniert werden. |
-
a function call expression that calls a function (or a constructor) that is not declared
constexpr
constexpr int n = std::numeric_limits<int>::max(); // OK: max() ist constexpr constexpr int m = std::time(nullptr); // Fehler: std::time() ist nicht constexpr
- a function call to a constexpr function which is declared, but not defined
- a function call to a constexpr function/constructor template instantiation where the instantiation fails to satisfy constexpr-Funktion/-Konstruktor requirements.
- a function call to a constexpr virtual function, invoked on an object whose dynamic type is constexpr-unknown
- an expression that would exceed the implementation-defined limits
-
an expression whose evaluation leads to any form of core language
undefined
oder fehlerhaft
(seit C++26)
behavior, except for any potential undefined behavior introduced by
Standardattribute
.
constexpr double d1 = 2.0 / 1.0; // OK constexpr double d2 = 2.0 / 0.0; // Fehler: nicht definiert constexpr int n = std::numeric_limits<int>::max() + 1; // Fehler: Überlauf int x, y, z[30]; constexpr auto e1 = &y - &x; // Fehler: undefiniert constexpr auto e2 = &z[20] - &z[3]; // OK constexpr std::bitset<2> a; constexpr bool b = a[2]; // UB, aber unbestimmt ob erkannt
- (bis C++17) a Lambda-Ausdruck
-
an lvalue-to-rvalue
implizite Konvertierung
unless applied to...
- ein glvalue vom Typ (möglicherweise cv-qualifiziert) std::nullptr_t
-
ein nicht-flüchtiger Literal-Typ-glvalue, der ein Objekt bezeichnet, das
in konstanten Ausdrücken verwendbar ist
int main() { const std::size_t tabsize = 50; int tab[tabsize]; // OK: tabsize ist ein konstanter Ausdruck // weil tabsize in konstanten Ausdrücken verwendbar ist // da es const-qualifizierten integralen Typ hat und // sein Initialisierer ein konstanter Initialisierer ist std::size_t n = 50; const std::size_t sz = n; int tab2[sz]; // Fehler: sz ist kein konstanter Ausdruck // weil sz nicht in konstanten Ausdrücken verwendbar ist // da sein Initialisierer kein konstanter Initialisierer war }
- ein nicht-flüchtiger Literal-Typ-glvalue, der sich auf ein nicht-flüchtiges Objekt bezieht, dessen Lebensdauer innerhalb der Auswertung dieses Ausdrucks begann
T*
es sei denn, der Zeiger hält einen Nullzeigerwert oder zeigt auf ein Objekt, dessen Typ
ähnlich
zu
T
ist
(seit C++26)
dynamic_cast
dessen Operand ein Glvalue ist, der sich auf ein Objekt bezieht, dessen dynamischer Typ constexpr-unbekannt ist
(since C++20)
reinterpret_cast
constexpr int incr(int& n) { return ++n; } constexpr int g(int k) { constexpr int x = incr(k); // Fehler: incr(k) ist kein Kern-Konstantenausdruck // weil die Lebensdauer von k // außerhalb des Ausdrucks incr(k) begann return x; } constexpr int h(int k) { int x = incr(k); // OK: x muss nicht mit einem Kern-Konstantenausdruck // initialisiert werden return x; } constexpr int y = h(1); // OK: initialisiert y mit dem Wert 2 // h(1) ist ein Kern-Konstantenausdruck, weil // die Lebensdauer von k innerhalb des Ausdrucks h(1) beginnt
typeid
expression applied to a glvalue of polymorphic type
und dieser Glvalue verweist auf ein Objekt, dessen dynamischer Typ constexpr-unbekannt ist
(seit C++20)
|
(since C++20) |
|
(since C++26) |
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 seit C++26 static_assert(always_throw()); // Fehler: ungefangene Ausnahme
goto
Anweisung
dynamic_cast
oder
typeid
Ausdruck
oder
new
Ausdruck
(seit C++26)
der eine Ausnahme werfen würde
wo keine Definition des Ausnahmetyps erreichbar ist
(seit C++26)
void g() { const int n = 0; constexpr int j = *&n; // OK: außerhalb eines Lambda-Ausdrucks [=] { constexpr int i = n; // OK: 'n' wird hier nicht ODR-genutzt und nicht erfasst. constexpr int j = *&n; // Ungültig: '&n' wäre eine ODR-Nutzung von 'n'. }; }
|
Hinweis: Wenn die ODR-Nutzung in einem Funktionsaufruf an einen Closure stattfindet, bezieht sie sich nicht auf this oder auf eine umschließende Variable, da sie auf ein Datenmitglied des Closures zugreift // OK: 'v' & 'm' werden ODR-genutzt, kommen aber nicht in einem konstanten Ausdruck // innerhalb des verschachtelten Lambdas vor auto monad = [](auto v){ return [=]{ return v; }; }; auto bind = [](auto m){ return [=](auto fvm){ return fvm(m()); }; }; // OK, Erfassungen von automatischen Objekten, die während der konstanten Ausdrucksauswertung erstellt wurden, zu haben. static_assert(bind(monad(2))(monad)() == monad(2)()); |
(seit C++17) |
Zusätzliche Anforderungen
Selbst wenn ein Ausdruck E nichts der oben genannten Dinge auswertet, ist implementierungsdefiniert, ob E ein Kernkonstanter Ausdruck ist, wenn die Auswertung von E zu Laufzeit-undefiniertem Verhalten führen würde.
Selbst wenn ein Ausdruck E nichts der oben genannten Dinge auswertet, ist es unspezifiziert, ob E ein Core Constant Expression ist, wenn die Auswertung von E eines der folgenden Dinge auswerten würde:
- Eine Operation mit undefiniertem Verhalten in der Standardbibliothek .
- Ein Aufruf des va_start Makros.
Für die Bestimmung, ob ein Ausdruck ein Kernkonstantenausdruck ist, wird die Auswertung des Rumpfes einer Elementfunktion von
std::
allocator
<
T
>
ignoriert, falls
T
ein Literaltyp ist.
Zum Zweck der Bestimmung, ob ein Ausdruck ein Kernkonstanter Ausdruck ist, wird die Auswertung eines Aufrufs eines trivialen Kopier-/Verschiebekonstruktors oder einer Kopier-/Verschiebezuweisung einer Union als Kopieren/Verschieben des aktiven Members der Union betrachtet, falls vorhanden.
|
Für die Bestimmung, ob ein Ausdruck ein Kernkonstantenausdruck ist, hat die Auswertung eines Identifikatorausdrucks, der eine structured binding bd benennt, die folgende Semantik:
|
(seit C++26) |
Während der Auswertung des Ausdrucks als Kernkonstanteausdruck werden alle Identifikatorausdrücke und Verwendungen von * this , die sich auf ein Objekt oder eine Referenz beziehen, deren Lebensdauer außerhalb der Auswertung des Ausdrucks begann, so behandelt, als würden sie sich auf eine spezifische Instanz dieses Objekts oder dieser Referenz beziehen, deren Lebensdauer und die aller Teilobjekte (einschließlich aller Union-Mitglieder) die gesamte Konstantenauswertung umfasst.
- Für ein solches Objekt das nicht in konstanten Ausdrücken verwendbar ist (seit C++20) , ist der dynamische Typ des Objekts constexpr-unknown .
- Für eine solche Referenz die nicht in konstanten Ausdrücken verwendbar ist (seit C++20) , wird die Referenz so behandelt, als würde sie an ein nicht näher spezifiziertes Objekt des referenzierten Typs gebunden, dessen Lebensdauer und die aller Unterobjekte die gesamte konstante Auswertung umfasst und dessen dynamischer Typ constexpr-unknown ist.
Integraler konstanter Ausdruck
Integraler konstanter Ausdruck ist ein Ausdruck vom integralen oder unbegrenzten Aufzählungstyp, der implizit in einen Prvalue konvertiert wird, wobei der konvertierte Ausdruck ein Kernkonstanter Ausdruck ist.
Wenn ein Ausdruck vom Klassentyp an einer Stelle verwendet wird, wo ein integraler konstanter Ausdruck erwartet wird, wird der Ausdruck kontextuell implizit konvertiert zu einem integralen Typ oder einem unbegrenzten Aufzählungstyp.
Konvertierter konstanter Ausdruck
Ein
konvertierter konstanter Ausdruck
vom Typ
T
ist ein Ausdruck, der
implizit konvertiert
wird zum Typ
T
, wobei der konvertierte Ausdruck ein konstanter Ausdruck ist und die implizite Konvertierungssequenz nur folgende Elemente enthält:
-
- constexpr benutzerdefinierte Konvertierungen
- Lvalue-zu-Rvalue-Konvertierungen
- Ganzzahlpromotionen
- nicht-verengende Ganzzahlkonvertierungen
- Gleitkommapromotionen
- nicht-verengende Gleitkommakonvertierungen
| (seit C++17) |
Und falls eine Referenzbindung stattfindet, kann es nur eine direkte Bindung sein.
Die folgenden Kontexte erfordern einen konvertierten konstanten Ausdruck:
- die constant-expression von case labels
- enumerator initializers wenn der zugrundeliegende Typ festgelegt ist
- ganzzahlige und Aufzählungs- (bis C++17) konstante template arguments
|
(seit C++14) |
|
(seit C++26) |
Ein kontextuell umgewandelter konstanter Ausdruck vom Typ bool ist ein Ausdruck, der kontextuell zu bool umgewandelt wird , wobei der umgewandelte Ausdruck ein konstanter Ausdruck ist und die Umwandlungssequenz 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 Bestandteilswerte eines Objekts obj werden wie folgt definiert:
Die Bestandteilsreferenzen eines Objekts obj umfassen folgende Referenzen:
Die Bestandteilswerte und Bestandteilsreferenzen einer Variable var werden wie folgt definiert:
Für jede Bestandteilsreferenz ref einer Variable var gilt: Wenn ref an ein temporäres Objekt oder dessen Unterobjekt gebunden ist, dessen Lebensdauer auf die von ref verlängert wurde, dann sind die Bestandteilswerte und -referenzen dieses temporären Objekts ebenfalls Bestandteilswerte und -referenzen von var , rekursiv. Constexpr-repräsentierbare EntitätenObjekte mit statischer Speicherdauer sind constexpr-referenzierbar an jedem Punkt im Programm.
Ein Objekt
obj
mit automatischer Speicherdauer ist
constexpr-referenzierbar
von einem Punkt
Ein Objekt oder eine Referenz
x
ist
constexpr-repräsentierbar
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 Ganzzahl- oder Aufzählungstyp besitzt.
Eine konstant initialisierte potenziell konstante Variable
var
ist
in konstanten Ausdrücken verwendbar
an einem Punkt
Offensichtlich konstant ausgewertete AusdrückeDie folgenden Ausdrücke (einschließlich Konvertierungen in den Zieltyp) sind offensichtlich konstant ausgewertet :
Ob eine Auswertung in einem offensichtlich konstanten Kontext stattfindet, kann durch
std::is_constant_evaluated
und
|
(seit C++20) |
Für die konstante Auswertung benötigte Funktionen und Variablen
Folgende Ausdrücke oder Konvertierungen sind potenziell konstant ausgewertet :
- offensichtlich konstant ausgewertete Ausdrücke
- potenziell ausgewertete Ausdrücke
- unmittelbare Teilausdrücke eines geschweiften Initialisiererlist (konstante Auswertung kann notwendig sein um zu bestimmen ob eine Konvertierung einschränkend ist )
- Adressoperator-Ausdrücke die innerhalb einer templatisierten Entität auftreten (konstante Auswertung kann notwendig sein um zu bestimmen ob ein solcher Ausdruck wertabhängig ist)
- Teilausdrücke eines der obigen die kein Teilausdruck eines verschachtelten nicht ausgewerteten Operanden sind
Eine Funktion ist für konstante Auswertung benötigt wenn sie eine constexpr-Funktion ist und benannt durch einen Ausdruck, der potenziell konstant ausgewertet wird.
Eine Variable ist für konstante Auswertung benötigt wenn sie entweder eine constexpr-Variable ist oder einen nicht-flüchtigen const-qualifizierten integralen Typ oder Referenztyp hat und der Identifikatorausdruck der sie bezeichnet potenziell konstant ausgewertet wird.
Definition einer defaulted-Funktion und Instanziierung einer Funktions-Template -Spezialisierung oder Variablen-Template -Spezialisierung (since C++14) werden ausgelöst, wenn die Funktion oder Variable (since C++14) für konstante Auswertung benötigt wird.
Konstanter Teilausdruck
Ein konstanter Teilausdruck ist ein Ausdruck, dessen Auswertung als Teilausdruck eines Ausdrucks e nicht verhindern würde, dass e ein Core Constant Expression ist, wobei e keiner der folgenden Ausdrücke ist:
| (seit C++20) |
Hinweise
| Feature-Test-Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_constexpr_in_decltype
|
201711L
|
(C++20)
(DR11) |
Generierung von Funktions- und Variablendefinitionen, wenn für konstante Auswertung benötigt |
__cpp_constexpr_dynamic_alloc
|
201907L
|
(C++20) | Operationen für dynamische Speicherdauer in constexpr Funktionen |
__cpp_constexpr
|
202306L
|
(C++26) | constexpr Cast von void * : in Richtung constexpr Type Erasure |
202406L
|
(C++26) | constexpr Placement new und new [ ] | |
__cpp_constexpr_exceptions
|
202411L
|
(C++26) | constexpr Exceptions: [1] , [2] |
Beispiel
|
Dieser Abschnitt ist unvollständig
Grund: Kein Beispiel |
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 94 | C++98 |
arithmetische konstante Ausdrücke konnten
keine Variablen und statische Datenelemente enthalten |
jetzt möglich |
| CWG 366 | C++98 |
Ausdrücke mit String-Literalen
könnten konstante Integralausdrücke sein |
sie sind es nicht |
| CWG 457 | C++98 |
Ausdrücke mit flüchtigen Variablen
könnten konstante Integralausdrü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-Glvalues konnten in konstanten Ausdrücken verwendet werden | verboten |
| CWG 1312 | C++11 |
reinterpret_cast
ist in konstanten Ausdrücken verboten,
aber Casts zu und von void * könnten denselben Effekt erzielen |
verbotene Konvertierungen
vom Typ cv void * zu einem Zeiger-auf-Objekt-Typ |
| CWG 1313 | C++11 |
undefiniertes Verhalten war erlaubt;
alle Zeigersubtraktionen waren verboten |
UB verboten; Zeigersubtraktion
innerhalb desselben Arrays erlaubt |
| CWG 1405 | C++11 |
für Objekte, die in konstanten Ausdrücken verwendbar sind,
waren ihre veränderlichen Unterobjekte ebenfalls verwendbar |
sie sind nicht verwendbar |
| CWG 1454 | C++11 |
Das Übergeben von Konstanten durch constexpr
Funktionen über 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 Adresskonstantenausdruck konnte nicht
die Adresse direkt nach dem Ende eines Arrays bezeichnen |
erlaubt |
| CWG 1535 | C++11 |
ein
typeid
-Ausdruck, dessen Operand von einem
polymorphen Klassentyp war, war kein Core Constant Expression, selbst wenn keine Laufzeitprüfung beteiligt war |
die Operandenbeschränkung
ist auf L-Werte von polymorphen Klassentypen begrenzt |
| CWG 1581 | C++11 |
für die konstante Auswertung benötigte Funktionen waren
nicht definiert oder instanziiert werden mussten |
erforderlich |
| 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 |
Das Binden des Werts eines temporären Objekts an eine Referenz mit statischer
Speicherdauer war ein konstanter Ausdruck |
es ist kein
konstanter Ausdruck |
| CWG 1872 | C++11 |
Kernkonstantenausdrücke könnten
constexpr
Funktions-Template-Instanziierungen aufrufen,
die die constexpr Funktionsanforderungen nicht erfüllen |
solche Instanziierungen
können nicht aufgerufen werden |
| CWG 1952 | C++11 |
Standardbibliothek undefinierte Verhaltensweisen
mussten diagnostiziert werden |
nicht spezifiziert ob
sie diagnostiziert werden |
| CWG 2022 | C++98 |
die Bestimmung von konstanten Ausdrücken könnte
davon abhängen, ob Copy Elision durchgeführt wird |
gehe davon aus, dass Copy Elision
immer durchgeführt wird |
| CWG 2126 | C++11 |
Konstant initialisierte, lebensdauer-verlängerte Temporaries von const-
qualifizierten Literaltypen waren nicht in konstanten Ausdrücken verwendbar |
verwendbar |
| CWG 2129 | C++11 | Ganzzahlige Literale waren keine konstanten Ausdrücke | sie sind es |
| CWG 2167 | C++11 |
Nicht-Mitglied-Referenzen lokal zu einer Auswertung
machten die Auswertung nicht-konstexpr |
Nicht-Mitglied-
Referenzen erlaubt |
| CWG 2278 | C++98 | die Lösung von CWG Issue 2022 war nicht implementierbar |
annehmen, dass Copy Elision
niemals durchgeführt wird |
| CWG 2299 | C++14 |
Es war unklar, ob Makros in
<cstdarg>
bei konstanter Auswertung verwendet werden können |
va_arg
verboten,
va_start
nicht spezifiziert
|
| CWG 2400 | C++11 |
Aufruf einer constexpr-Virtualfunktion auf einem Objekt, das nicht
in konstanten Ausdrücken verwendbar ist und dessen Lebensdauer außerhalb des Ausdrucks begann, der den Aufruf enthält, könnte ein konstanter Ausdruck sein |
es ist kein
konstanter Ausdruck |
| CWG 2490 | C++20 |
(Pseudo-)Destruktoraufrufe fehlten
Einschränkungen bei konstanter Auswertung |
Einschränkung hinzugefügt |
| CWG 2552 | C++23 |
bei der Auswertung eines konstanten Kernausdrucks konnte der Kontrollfluss
nicht durch eine Deklaration einer Nicht-Block-Variable verlaufen |
es kann |
| CWG 2558 | C++11 | Ein unbestimmter Wert könnte ein konstanter Ausdruck sein | kein konstanter Ausdruck |
| CWG 2647 | C++20 | Variablen von volatile-qualifizierten Typen könnten potenziell konstant sein | sind sie nicht |
| CWG 2763 | C++11 |
die Verletzung von
[[
noreturn
]]
musste nicht
während der konstanten Auswertung erkannt werden |
erforderlich |
| CWG 2851 | C++11 |
konvertierte konstante Ausdrücke erlaubten
keine Gleitkomma-Konvertierungen |
nicht-verengende
Gleitkomma-Konvertierungen erlauben |
| CWG 2907 | C++11 |
Kernkonstantenausdrücke konnten keine
Lvalue-zu-Rvalue-Konvertierungen auf std::nullptr_t -Glvalues anwenden |
können solche
Konvertierungen anwenden |
| CWG 2909 | C++20 |
eine Variable ohne Initialisierer konnte nur
konstant-initialisiert werden, wenn ihre Standardinitialisierung zur Durchführung einer Initialisierung führt |
kann nur konstant-
initialisiert werden, wenn ihr Typ const-default-initializable ist |
| CWG 2924 |
C++11
C++23 |
Es war nicht spezifiziert, ob ein Ausdruck, der gegen
die Constraints von
[[
noreturn
]]
(C++11) oder
[[
assume
]]
(C++23) verstößt, ein Core Constant Expression ist
|
Es ist
implementierungsdefiniert |
| P2280R4 | C++11 |
Die Auswertung eines Ausdrucks, der einen Identifikatorausdruck
oder * this enthält, der sich auf ein Objekt oder eine Referenz bezieht, dessen Lebensdauer außerhalb dieser Auswertung begann, ist keine konstante Ausdruck |
es kann ein
konstanter Ausdruck sein |
Siehe auch
constexpr
Spezifizierer
(C++11)
|
gibt an, dass der Wert einer Variable oder Funktion zur Kompilierzeit berechnet werden kann |
|
(C++11)
(deprecated in C++17)
(removed in C++20)
|
prüft, ob ein Typ ein Literaltyp ist
(Klassentemplate) |
|
C-Dokumentation
für
Konstante Ausdrücke
|
|