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 вне объявления факториальной функции.

Другие вопросы по тегам