Esiste una proprietà molto accurata delle espressioni costanti in C ++: la loro valutazione non può avere un comportamento indefinito ( 7.7.4.7 ):
Un'espressione e è un'espressione costante centrale a meno che la valutazione di e, seguendo le regole della macchina astratta ([intro.execution]), valuti una delle seguenti:
...
un'operazione che avrebbe un comportamento indefinito come specificato da [introduzione] a [cpp] di questo documento [Nota: tra cui, ad esempio, overflow di interi con segno ([prop.espr.]), aritmetica di alcuni puntatori ([expr.add]), divisione per zero, o determinate operazioni di spostamento - nota finale];
Cercare di memorizzare il valore di 13!
in a produce inconstexpr int
effetti un buon errore di compilazione :
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;
}
Produzione:
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.
(A proposito, perché l'errore dice "call to 'f (3)'", mentre è una chiamata a f (13)? ..)
Quindi, rimuovo constexpr
da x
, ma crea f
un consteval
. Secondo i documenti :
consteval: specifica che una funzione è una funzione immediata, ovvero ogni chiamata alla funzione deve produrre una costante di tempo di compilazione
Mi aspetto che un tale programma provochi di nuovo un errore di compilazione. Invece, il programma viene compilato ed eseguito con UB .
Perché?
UPD: i commentatori hanno suggerito che si tratta di un bug del compilatore. L'ho segnalato: https://bugs.llvm.org/show_bug.cgi?id=43714
in call to 'f(3)'
- Questo è strano! Ex. Se mettif(123)
clang avvertein call to 'f(119)'
.