Einführung
constexpr
wurde nicht eingeführt, um der Implementierung mitzuteilen, dass etwas in einem Kontext bewertet werden kann, der einen konstanten Ausdruck erfordert ; Konforme Implementierungen konnten dies vor C ++ 11 beweisen.
Was eine Implementierung nicht beweisen kann, ist die Absicht eines bestimmten Codes:
- Was möchte der Entwickler mit dieser Entität ausdrücken?
- Sollten wir blind zulassen, dass Code in einem konstanten Ausdruck verwendet wird , nur weil er zufällig funktioniert?
Was wäre die Welt ohne constexpr
?
Angenommen, Sie entwickeln eine Bibliothek und stellen fest, dass Sie die Summe jeder Ganzzahl im Intervall berechnen möchten (0,N]
.
int f (int n) {
return n > 0 ? n + f (n-1) : n;
}
Der Mangel an Absicht
Ein Compiler kann leicht beweisen, dass die obige Funktion in einem Konstantenausdruck aufrufbar ist, wenn das übergebene Argument während der Übersetzung bekannt ist. Aber Sie haben dies nicht als Absicht deklariert - es war einfach so.
Jetzt kommt jemand anderes, liest Ihre Funktion und führt die gleiche Analyse durch wie der Compiler. " Oh, diese Funktion kann in einem konstanten Ausdruck verwendet werden!" und schreibt den folgenden Code.
T arr[f(10)]; // freakin' magic
Die Optimierung
Sie als "großartiger" Bibliotheksentwickler entscheiden, dass f
das Ergebnis beim Aufrufen zwischengespeichert werden soll. Wer möchte immer wieder die gleichen Werte berechnen?
int func (int n) {
static std::map<int, int> _cached;
if (_cached.find (n) == _cached.end ())
_cached[n] = n > 0 ? n + func (n-1) : n;
return _cached[n];
}
Das Ergebnis
Durch die Einführung Ihrer albernen Optimierung haben Sie einfach jede Verwendung Ihrer Funktion unterbrochen, die sich zufällig in einem Kontext befand, in dem ein konstanter Ausdruck erforderlich war.
Sie haben nie versprochen, dass die Funktion in einem konstanten Ausdruck verwendet werden kann , und ohne sie constexpr
gäbe es keine Möglichkeit, ein solches Versprechen abzugeben.
Also, warum brauchen wir constexpr
?
Die Hauptverwendung von constexpr besteht darin, die Absicht zu erklären .
Wenn eine Entität nicht als gekennzeichnet ist, sollte constexpr
sie niemals in einem konstanten Ausdruck verwendet werden . und selbst wenn dies der Fall ist, verlassen wir uns darauf, dass der Compiler einen solchen Kontext diagnostiziert (weil er unsere Absicht missachtet).
constexpr
? Wenn ja, kann ich eine Verwendung sehen.