W C ++ istnieje bardzo zgrabna właściwość wyrażeń stałych: ich ocena nie może mieć niezdefiniowanego zachowania ( 7.7.4.7 ):
Wyrażenie e jest podstawowym stałym wyrażeniem, chyba że ocena e, zgodnie z regułami maszyny abstrakcyjnej ([intro. Wykonanie]), ocenia jedną z następujących czynności:
...
operacja, która miałaby niezdefiniowane zachowanie określone w [intro] do [cpp] tego dokumentu [Uwaga: w tym, na przykład, przepełnienie liczb całkowitych ze znakiem ([expr.prop]), pewna arytmetyka wskaźnika ([expr.add]), dzielenie przez zero lub niektóre operacje zmiany - przypis końcowy];
Próba zapisania wartości 13!
w constexpr int
rzeczywiście daje ładny błąd kompilacji :
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;
}
Wynik:
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.
(BTW, dlaczego błąd mówi „call to 'f (3)'”, podczas gdy jest to call do f (13)?).
Następnie zdjąć constexpr
z x
, ale upewnij . Według dokumentów :f
consteval
consteval - określa, że funkcja jest funkcją natychmiastową, to znaczy każde wywołanie funkcji musi dawać stałą czasową kompilacji
Oczekuję, że taki program ponownie spowodowałby błąd kompilacji. Zamiast tego program kompiluje się i działa z UB .
Dlaczego?
UPD: Komentatorzy sugerowali, że jest to błąd kompilatora. Zgłosiłem to: https://bugs.llvm.org/show_bug.cgi?id=43714
in call to 'f(3)'
- to jest dziwne! Dawny. Jeśli włożyszf(123)
klang, ostrzegain call to 'f(119)'
.