C ++ 'da sabit ifadelerin çok düzgün bir özelliği vardır: değerlendirmelerinin tanımlanmamış davranışı olamaz ( 7.7.4.7 ):
E ifadesi, soyut makinenin kurallarına ([intro.execution]) uygun olarak e değerlendirmesi aşağıdakilerden birini değerlendirmediği sürece, temel sabit bir ifadedir:
...
bu belgenin [intro] ila [cpp] 'de belirtildiği gibi tanımlanmamış davranışa sahip bir işlem [Not: örneğin işaretli tamsayı taşması ([expr.prop]), belirli işaretçi aritmetiği ([expr.add]), sıfıra bölme veya belirli vardiya işlemleri - son not];
Değerini depolamak için çalışırken 13!
bir de constexpr int
gerçekten iyi bir derleme hata verir :
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;
}
Çıktı:
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 hata neden f (13) 'e bir çağrı iken "f (3)" çağrısını söylüyor? ..)
Sonra, ben kaldırmak constexpr
gelen x
, ancak yapmak f
bir consteval
. Dokümanlara göre :
consteval - bir işlevin anlık bir işlev olduğunu, yani işleve yapılan her çağrının bir derleme zamanı sabiti üretmesi gerektiğini belirtir
Böyle bir programın tekrar derleme hatasına neden olmasını bekliyorum. Ancak bunun yerine, program derlenir ve UB ile çalışır .
Neden?
UPD: Yorum yapanlar bunun bir derleyici hatası olduğunu öne sürdüler. Rapor ettim: https://bugs.llvm.org/show_bug.cgi?id=43714
in call to 'f(3)'
- bu tuhaf! Ör. Eğerf(123)
clang koyarsanız hakkında uyarırin call to 'f(119)'
.