Ada properti yang sangat rapi dari ekspresi konstan dalam C ++: evaluasi mereka tidak dapat memiliki perilaku yang tidak terdefinisi ( 7.7.4.7 ):
Ekspresi e adalah ekspresi konstanta inti kecuali evaluasi e, mengikuti aturan mesin abstrak ([intro.execution]), akan mengevaluasi salah satu dari yang berikut:
...
sebuah operasi yang akan memiliki perilaku yang tidak ditentukan sebagaimana ditentukan dalam [intro] melalui [cpp] dokumen ini [Catatan: termasuk, misalnya, menandatangani integer overflow ([expr.prop]), aritmatika pointer tertentu ([expr.add]), pembagian dengan nol, atau operasi shift tertentu - catatan akhir];
Mencoba menyimpan nilai 13!
dalam constexpr int
memang menghasilkan kesalahan kompilasi yang bagus :
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;
}
Keluaran:
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 mengapa kesalahan mengatakan "panggil ke 'f (3)'", sementara itu adalah panggilan ke f (13)? ..)
Kemudian, saya menghapus constexpr
dari x
, tetapi membuat f
sebuah consteval
. Menurut dokumen :
consteval - menetapkan bahwa fungsi adalah fungsi langsung, yaitu, setiap panggilan ke fungsi harus menghasilkan konstanta waktu kompilasi
Saya berharap bahwa program seperti itu lagi akan menyebabkan kesalahan kompilasi. Tetapi sebaliknya, program ini mengkompilasi dan berjalan dengan UB .
Mengapa demikian?
UPD: Komentator menyarankan bahwa ini adalah bug penyusun. Saya melaporkannya: https://bugs.llvm.org/show_bug.cgi?id=43714
in call to 'f(3)'
- ini aneh! Ex. Jika Anda menaruhf(123)
dentang memperingatkanin call to 'f(119)'
.