In C++ 14 die Regeln für constexpr Funktion waren entspannt und das Papier N3597: Relaxing constraints on constexpr functions. Das Papier geht in die Grundlagen und die Auswirkungen, und es enthält die folgenden (emphasis Mine):
wie in C++ 11 wird das Schlüsselwort constexpr markieren Funktionen verwendet, welche die Umsetzung erforderlich ist, während der zur Bewertung Übersetzung, wenn sie aus einem Kontext verwendet werden, in dem ein konstanter Ausdruck benötigt wird. Jeder gültige C++ - Code ist in constexpr-Funktionen zulässig, einschließlich der Erstellung und Änderung lokaler Variablen und fast aller Anweisungen, , mit der Einschränkung, dass eine constexpr-Funktion innerhalb eines konstanten Ausdrucks verwendet werden kann. Ein konstanter Ausdruck kann immer noch Nebenwirkungen haben, die für die Bewertung und deren Ergebnis lokal sind.
und:
Eine Handvoll syntaktischen Beschränkungen constexpr Funktionen sind beibehalten:
- ASM-Deklarationen nicht zulässig sind.
- try-blocks und function-try-blocks sind nicht erlaubt.
- Deklarationen von Variablen mit statischer und Thread-Speicherdauer haben einige Einschränkungen (siehe unten).
und wir können dies in N4140 Abschnitt behandelt finden 7.1.5
[dcl.constexpr] die sagt:
Die Definition einer constexpr Funktion soll die folgenden Bedingungen erfüllen:
es soll nicht virtuell sein (10.3);
Der Rückgabetyp muss ein Literaltyp sein;
jeder seiner Parametertypen muss ein Literaltyp sein;
seine Funktion Körper wird sein = löschen = default oder eine Verbindung-Anweisung, die nicht
Das letzte Beispiel zeigt, wie incr
in einem constexpr verwendet werden:
constexpr int h(int k) {
int x = incr(k); // OK: incr(k) is not required to be 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 h(1)
und der Regel, dass the lifetime of k begins inside h(1)
bedeckt ist:
- Modifikation ein Objekt (5.17, 5.2.6, 5.3.2) unle ss wird auf einen nichtflüchtigen Wert des Literaltyps angewendet, der sich auf ein nichtflüchtiges Objekt bezieht, dessen Lebensdauer mit der Auswertung von e begann;
Die Formulierung in 7.1.5
[dcl.constexpr] zeigt uns, warum incr
eine gültige constexpr ist:
Für eine nicht-Vorlage, nicht ausgefallene constexpr Funktion oder eine nicht-Vorlage consExpr-Konstruktor, wenn keine Argumentwerte vorhanden sind, sodass ein Aufruf der Funktion oder des Konstruktors ein ausgewerteter Unterausdruck eines konstanten Kernausdrucks sein könnte (5.19), ist das Programm schlecht gebildet; nein Diagnose erforderlich.
Wie das modifizierte Beispiel von T.C.:
constexpr int& as_lvalue(int&& i){ return i; }
constexpr int x = incr(as_lvalue(1)) ;
zeigt, können wir incr
als subexpression eines Kern konstanten Ausdruck und deshalb ist es nicht schlecht gebildet verwenden in der Tat.
Ich bin mir nicht sicher, aber braucht "constexpr", für Funktionen, nur einen Fall, für den es zur Kompilierzeit auf etwas optimiert werden kann? – VermillionAzure
Ich bekomme einen Kompilierfehler, wenn ich versuche, * 'incr()' zu verwenden, um eine 'constexpr'-Variable zu initialisieren. –