В C ++ існує дуже акуратна властивість константних виразів: їх оцінка не може мати визначеної поведінки ( 7.7.4.7 ):
Вираз e - основний постійний вираз, якщо тільки оцінка e, дотримуючись правил абстрактної машини ([intro.execution]), не оцінила б одне з наступних:
...
операція, яка мала б не визначену поведінку, як зазначено в [intro] через [cpp] цього документа [Примітка: включаючи, наприклад, підписане ціле число переповнення ([expr.prop]), деяку арифметику вказівника ([expr.add]), поділ на нуль або певні операції зсуву - кінцева примітка];
Намагання зберегти значення 13!
в constexpr int
дійсно призводить до гарної помилки компіляції :
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;
}
Вихід:
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 чому помилка говорить "виклик до 'f (3)'", тоді як це дзвінок до f (13)? ..)
Потім я видаляю constexpr
з x
, але зробити . Згідно з документами :f
consteval
consteval - визначає, що функція є безпосередньою функцією, тобто кожен виклик функції повинен виробляти константу часу компіляції
Я очікую, що така програма знову призведе до помилки компіляції. Але натомість програма компілює та працює з UB .
Чому так?
UPD: Коментатори припустили, що це помилка компілятора. Про це я повідомив: https://bugs.llvm.org/show_bug.cgi?id=43714
in call to 'f(3)'
- це дивно! Вих. Якщо поставитиf(123)
кланг попереджає проin call to 'f(119)'
.