Ответ 1
объяснение
Некоторые компиляторы (особенно 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; // false
std::cout << (is_cube(value)) << std::endl; // false
std::cout << (is_cube_inline(value)) << std::endl; // false
}
В отличие от этого примера, где мы используем те же настройки компилятора, но предоставляем значение во время компиляции, что приводит к более точной оценке во время компиляции.