编译时递归如何工作?

我在这里找到了一个代码打印1到1000没有循环或条件 有人可以解释编译时间递归是如何工作的,无法在谷歌中找到它
// 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>();
}
谢谢!     
已邀请:
它反复实例化
f1<N>
模板,减少
N
的值(
f1<N>()
调用
f1<N-1>
,依此类推)。
N==1
的显式特化结束递归:一旦
N
变为1,编译器将选择专用函数而不是模板化函数。
f1<1000>()
使编译器实例化
f1<N>
999次(不计入最终调用
f1<1>
)。这就是为什么编译大量使用模板元编程技术的代码需要一段时间的原因。 整个过程在很大程度上依赖于编译器的优化技能 - 理想情况下,它应该完全取消递归(仅用作模拟使用模板的
for
循环的hack)。     
它在概念上与运行时递归几乎相同。
f1<1000>
调用
f1<999>
然后打印出1000.
f1<999>
调用
f1<998>
然后打印出999等等。一旦达到1,模板专门化作为中止递归的基本情况。     
很简单,每个模板实例都会使用更改的参数创建一个新函数。就像你定义的那样:f1_1000(),f1_999()等等。 每个函数调用该函数,其名称少于1。因为有一个不同的模板,而不是递归,为了定义f1_1(),我们也有一个停止案例。     
这不能保证是纯编译时递归。编译器必须为2到1000的所有参数值实例化函数
f1()
,它们将相互调用。 然后编译器可能会看到这些调用只能变成一系列
cout << ...
语句。也许它会消除调用,也许不会 - 这取决于编译器。从C ++的角度来看,这是一系列函数调用,只要它不改变行为,编译器就可以做任何事情。     
您在此处解释了因子计算。 顺便说一句,你的功能不适用于负数。     

要回复问题请先登录注册