Konstante Ausdrücke in C ++ haben eine sehr nette Eigenschaft: Ihre Auswertung kann kein undefiniertes Verhalten haben ( 7.7.4.7 ):
Ein Ausdruck e ist ein konstanter Kernausdruck, es sei denn, die Auswertung von e nach den Regeln der abstrakten Maschine ([intro.execution]) würde eine der folgenden auswerten:
...
eine Operation, die ein undefiniertes Verhalten aufweisen würde, wie in [intro] bis [cpp] dieses Dokuments angegeben [Hinweis: einschließlich beispielsweise eines vorzeichenbehafteten Ganzzahlüberlaufs ([expr.prop]), einer bestimmten Zeigerarithmetik ([expr.add]), Division durch Null oder bestimmte Schaltvorgänge - Endnote];
Der Versuch, den Wert von 13!
in a zu speichern, führt constexpr int
tatsächlich zu einem netten Kompilierungsfehler :
constexpr int f(int n)
{
int r = n--;
for (; n > 1; --n) r *= n;
return r;
}
int main()
{
constexpr int x = f(13);
return x;
}
Ausgabe:
9:19: error: constexpr variable 'x' must be initialized by a constant expression
constexpr int x = f(13);
^ ~~~~~
4:26: note: value 3113510400 is outside the range of representable values of type 'int'
for (; n > 1; --n) r *= n;
^
9:23: note: in call to 'f(3)'
constexpr int x = f(13);
^
1 error generated.
(Übrigens, warum sagt der Fehler "Aufruf von 'f (3)'", während es sich um einen Aufruf von f (13) handelt? ..)
Dann entferne ich constexpr
von x
, mache aber f
eine consteval
. Laut den Dokumenten :
consteval - Gibt an, dass eine Funktion eine unmittelbare Funktion ist, dh, jeder Aufruf der Funktion muss eine Konstante für die Kompilierungszeit erzeugen
Ich erwarte, dass ein solches Programm erneut einen Kompilierungsfehler verursachen würde. Stattdessen wird das Programm kompiliert und mit UB ausgeführt .
Warum ist das so?
UPD: Kommentatoren schlugen vor, dass dies ein Compiler-Fehler ist. Ich habe es gemeldet: https://bugs.llvm.org/show_bug.cgi?id=43714
in call to 'f(3)'
- das ist merkwürdig! Ex. Wenn Sief(123)
klirren, warntin call to 'f(119)'
.