В 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.
(Кстати, почему ошибка говорит «вызов 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)'
- это странно! Ex. Если вы поставитеf(123)
Clang предупреждает оin call to 'f(119)'
.