Пояснення
Деякі компілятори (зокрема GCC) використовують більшу точність при обчисленні виразів під час компіляції. Якщо вираз залежить лише від постійних входів та літералів, він може обчислюватися під час компіляції, навіть якщо вираз не призначений змінній constexpr. Відбудеться це чи ні, залежить від:
- Складність виразу
- Поріг, який компілятор використовує як граничний показник при спробі виконати оцінку часу компіляції
- Інші евристики, що використовуються в особливих випадках (наприклад, коли дзвін лунає)
Якщо вираз надано явно, як у першому випадку, воно має меншу складність, і компілятор, ймовірно, оцінить його під час компіляції.
Подібним чином, якщо функція позначена як вбудована, компілятор, швидше за все, оцінить її під час компіляції, оскільки вбудовані функції підвищують поріг, при якому може відбутися оцінка.
Більш високі рівні оптимізації також збільшують цей поріг, як у прикладі -Ofast, де всі вирази оцінюються як істинні для gcc завдяки вищій точності оцінки часу компіляції.
Ми можемо спостерігати таку поведінку тут у провіднику компілятора. При компіляції з -O1 під час компіляції обчислюється лише функція, позначена вбудованим, але при -O3 обидві функції оцінюються під час компіляції.
NB: У прикладах компілятора-дослідника я використовую printfзамість iostream, оскільки це зменшує складність основної функції, роблячи ефект більш помітним.
Демонстрація, що inlineне впливає на оцінку роботи
Ми можемо гарантувати, що жоден з виразів не обчислюється під час компіляції, отримуючи значення зі стандартного вводу, і коли ми це робимо, усі 3 вирази повертають false, як показано тут: 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;
}
На відміну від цього прикладу , де ми використовуємо ті самі налаштування компілятора, але надаємо значення під час компіляції, що призводить до більш точної оцінки часу компіляції.