Explicación
Algunos compiladores (especialmente GCC) utilizan una mayor precisión al evaluar expresiones en tiempo de compilación. Si una expresión depende solo de entradas constantes y literales, se puede evaluar en tiempo de compilación incluso si la expresión no está asignada a una variable constexpr. Si esto ocurre o no depende de:
- La complejidad de la expresión
- El umbral que el compilador usa como límite cuando intenta realizar la evaluación del tiempo de compilación
- Otras heurísticas que se utilizan en casos especiales (como cuando el ruido elide los bucles)
Si se proporciona explícitamente una expresión, como en el primer caso, tiene menor complejidad y es probable que el compilador la evalúe en el momento de la compilación.
De manera similar, si una función está marcada en línea, es más probable que el compilador la evalúe en tiempo de compilación porque las funciones en línea elevan el umbral en el que puede ocurrir la evaluación.
Los niveles de optimización más altos también aumentan este umbral, como en el ejemplo -Ofast, donde todas las expresiones se evalúan como verdaderas en gcc debido a una evaluación en tiempo de compilación de mayor precisión.
Podemos observar este comportamiento aquí en el explorador del compilador. Cuando se compila con -O1, solo la función marcada en línea se evalúa en tiempo de compilación, pero en -O3 ambas funciones se evalúan en tiempo de compilación.
NB: En los ejemplos del compilador-explorador, utilizo printfiostream en su lugar porque reduce la complejidad de la función principal, haciendo que el efecto sea más visible.
Demostrar que inlineno afecta la evaluación del tiempo de ejecución
Podemos asegurarnos de que ninguna de las expresiones se evalúe en tiempo de compilación obteniendo el valor de la entrada estándar, y cuando hacemos esto, las 3 expresiones devuelven falso como se demuestra aquí: https://ideone.com/QZbv6X
#include <cmath>
#include <iostream>
bool is_cube(double r)
{
return floor(cbrt(r)) == cbrt(r);
}
bool inline is_cube_inline(double r)
{
return floor(cbrt(r)) == cbrt(r);
}
int main()
{
double value;
std::cin >> value;
std::cout << (floor(cbrt(value)) == cbrt(value)) << std::endl;
std::cout << (is_cube(value)) << std::endl;
std::cout << (is_cube_inline(value)) << std::endl;
}
Contraste con este ejemplo , donde usamos la misma configuración del compilador pero proporcionamos el valor en tiempo de compilación, lo que resulta en una evaluación de mayor precisión en tiempo de compilación.