Как работает рекурсия времени компиляции?
Я нашел код здесь печатать 1 до 1000 без петли или conditionals
может кто-нибудь объяснить, как работает рекурсия времени компиляции, не смог найти его в google
// compile time recursion
template<int N> void f1()
{
f1<N-1>();
cout << N << 'n';
}
template<> void f1<1>()
{
cout << 1 << 'n';
}
int main()
{
f1<1000>();
}
спасибо!
5 ответов
он неоднократно создает f1<N>
шаблон с уменьшающимися значениями для N
(f1<N>()
звонки f1<N-1>
и так далее). Явная специализация для N==1
завершает рекурсию: как только N
становится 1, компилятор выберет специализированную функцию, а не шаблонную.
f1<1000>()
компилятор инстанцировать f1<N>
999 раз (не считая последнего вызова f1<1>
). Именно по этой причине для компиляции кода может потребоваться некоторое время широко использует методы метапрограммирования шаблонов.
все это сильно зависит от навыков оптимизации компилятора-в идеале, он должен удалить рекурсию (которая служит только для взлома, чтобы эмулировать for
цикл с использованием шаблонов) полностью.
он работает концептуально почти так же, как рекурсия во время выполнения. f1<1000>
звонки f1<999>
и затем печатает 1000. f1<999>
звонки f1<998>
а затем печатает 999 и т. д. Как только он достигает 1, специализация шаблона действует как базовый случай для отмены рекурсии.
достаточно просто, каждый экземпляр шаблона создает новую функцию с измененным параметром. Например, если вы определили: f1_1000 (), f1_999 () и так далее.
каждая функция вызывает функцию с 1 меньше в его имени. Поскольку существует другой шаблон, не рекурсивный, для определения f1_1 () у нас также есть стоп-кейс.
это не гарантируется как чистая рекурсия во время компиляции. Компилятор должен будет создать экземпляр function f1()
для всех параметров значение от 2 до 1000 и они будут называть друг друга.
тогда компилятор может увидеть, что эти вызовы можно просто превратить в последовательность cout << ...
заявления. Возможно, это устраняет вызовы, возможно, нет - это зависит от компилятора. С точки зрения C++ это цепочка вызовов функций, и компилятор может делать все, что угодно, если это не так изменить поведение.
вычисления факториала объяснил здесь.
Кстати, обратите внимание, что ваша функция не работает для отрицательных чисел.