gcc 4.7 и рекурсивные функции constexpr
Я немного играю с constexpr
рекурсия и попытаться увидеть, как она компилируется, и я не понимаю, при каких обстоятельствах gcc
выбрать для расчета рекурсии во время компиляции или во время выполнения.
Я использую следующий код факториального расчета:
#include <iostream>
constexpr unsigned int factorial(unsigned int i)
{
return i > 0 ? i*factorial(i-1) : 1;
}
int main(void)
{
std::cout << factorial(X) << std::endl;
}
и я меняю значение x
в факториале.
- При компиляции без оптимизации выражение не вычисляется во время компиляции.
- При компиляции с
-O1
флаг, выражение все еще не вычисляется во время компиляции. - С
-O2
, выражение вычисляется во время компиляции, еслиx < 9
, После этого значения факториал внедряется в виде цикла. Изменение значения-fconstexpr-depth
флаг ничего не меняет. - С
-O3
, выражение вычисляется во время компиляцииif x < 7
, После этого значения факториал внедряется с расширением x86 xmm. - Если я изменю произведение на сумму в факториальной функции, я получу расчет времени компиляции до
10000
или более и уменьшая или увеличивая значение-fconstexpr-depth
ничего не меняет
Кто-нибудь знает, каковы правила для gcc 4.7 для реализации рекурсивной функции как во время компиляции, так и во время выполнения?
2 ответа
constexpr
гарантированно будет оцениваться во время компиляции, если это необходимо во время компиляции. Например, это гарантированно будет вычислено во время компиляции, потому что enum
значения должны быть постоянными:
enum { VALUE = factorial(X) };
cout << VALUE << endl;
В любом случае, когда он не нужен во время компиляции, он имеет тот же эффект, что и объявление inline
Это всего лишь подсказка, и компилятор может делать то, что хочет.
Как inline
большинство компиляторов в настоящее время полностью игнорируют вашу подсказку. По соображениям производительности, компилятор хочет иметь возможность встроить что-то, даже если вы этого не просили, и имеет свой собственный алгоритм, чтобы определить, когда это стоит и не стоит, так зачем ему смотреть на inline
ключевое слово вообще?
Объявление функции constexpr
не означает, что он будет оцениваться во время компиляции. Это означает, что его можно использовать для вычисления значения, которое необходимо во время компиляции. В любом другом контексте это просто обычная функция, и она будет оцениваться во время выполнения, если только компилятор не определит, что оценка ее во время компиляции удовлетворяет правилу "как будто" и его стоит выполнить.
Другими словами, я ожидаю, что вы найдете точно такой же шаблон выполнения во время компиляции / выполнения, если вы уйдете constexpr
вне объявления факториальной функции.