Hay una propiedad muy clara de las expresiones constantes en C ++: su evaluación no puede tener un comportamiento indefinido ( 7.7.4.7 ):
Una expresión e es una expresión constante central a menos que la evaluación de e, siguiendo las reglas de la máquina abstracta ([intro.execution]), evalúe uno de los siguientes:
...
una operación que tendría un comportamiento indefinido como se especifica en [introducción] a [cpp] de este documento [Nota: incluyendo, por ejemplo, desbordamiento de entero con signo ([expr.prop]), cierta aritmética de puntero ([expr.add]), división por cero, o ciertas operaciones de turno - nota final];
Intentar almacenar el valor de 13!
en de constexpr int
hecho produce un buen error de compilación :
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;
}
Salida:
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.
(Por cierto, ¿por qué el error dice "llamar a 'f (3)'", mientras que es una llamada a f (13)? ..)
Luego, elimino constexpr
de x
, pero hago f
un consteval
. Según los documentos :
consteval: especifica que una función es una función inmediata, es decir, cada llamada a la función debe producir una constante de tiempo de compilación
Espero que dicho programa vuelva a causar un error de compilación. Pero en cambio, el programa compila y se ejecuta con UB .
¿Porqué es eso?
UPD: Los comentaristas sugirieron que este es un error del compilador. Lo informé: https://bugs.llvm.org/show_bug.cgi?id=43714
in call to 'f(3)'
- ¡esto es extraño! Ex. Si le pones unf(123)
sonido metálico avisa sobrein call to 'f(119)'
.