c++ - Enteros constantes y evaluación constante
constexpr c++20 (1)
¿No es divertido la evaluación constante?
Hay algunos lugares en el lenguaje donde tratamos de hacer una evaluación constante y si eso falla, recurrimos a la evaluación no constante. La inicialización estática es uno de esos lugares, la inicialización de enteros constantes es otro.
Que pasa con:
int const i = f();
es que esto
podría ser
una evaluación constante, pero no necesariamente tiene que serlo.
Debido a que los enteros constantes (no
constexpr
) todavía se pueden usar como expresiones constantes, si cumplen con todas las demás condiciones, tenemos que intentarlo.
Por ejemplo:
const int n = 42; // const, not constexpr
std::array<int, n> arr; // n is a constant expression, this is ok
Así que intentemos hacerlo, llamamos
f()
como una expresión constante.
En este contexto,
std::is_constant_evaluated()
es
true
, por lo que golpeamos la rama con el
throw
y terminamos fallando.
No se puede
throw
durante la evaluación constante, por lo que nuestra evaluación constante falla.
Pero luego retrocedemos e intentamos nuevamente, esta vez llamando a
f()
como una expresión no constante (es decir,
std::is_constant_evaluated()
es
false
).
Esta ruta tiene éxito, dándonos
1
, por lo que se inicializa con el valor
1
.
Pero notablemente,
no soy
una expresión constante en este punto.
¡Un
static_assert(i == 1)
posterior
static_assert(i == 1)
estaría mal formado porque el inicializador de
i
no
era una expresión constante!
Aunque la ruta de inicialización no constante sucede (de lo contrario) satisface por completo los requisitos de una expresión constante.
Tenga en cuenta que si lo intentamos:
constexpr int i = f();
Esto habría fallado porque no podemos recurrir a la inicialización no constante.
Considere el siguiente programa:
#include <iostream>
#include <type_traits>
constexpr int f() {
if (std::is_constant_evaluated())
return -1;
else return 1;
}
int main() {
int const i = f();
std::cout << i;
}
Imprime
-1
cuando se ejecuta
(wandbox).
Sin embargo, si hago que la función
throw
cuando se evalúa en tiempo de compilación ::
#include <iostream>
#include <type_traits>
constexpr int f() {
if (std::is_constant_evaluated())
throw -1; // <----------------------- Changed line
else return 1;
}
int main() {
int const i = f();
std::cout << i;
}
compila bien y genera 1 (wandbox). ¿Por qué no recibí un error de compilación en su lugar?