代码
#include <iostream>
using namespace std;
template<int n> struct Fibo { static int x; };
template<> int Fibo<0>::x = 1;
template<> int Fibo<1>::x = 1;
template<int n> int Fibo<n>::x = Fibo<n-1>::x + Fibo<n-2>::x; //marked line
int main() {
cout << Fibo<5>::x << endl;
cout << Fibo<4>::x << endl;
cout << Fibo<3>::x << endl;
cout << Fibo<2>::x << endl;
cout << Fibo<1>::x << endl;
cout << Fibo<0>::x << endl;
return 0;
}
输出
0
0
1
2
1
1
在 VC++ 中。 (根据用户 M M. 它在 gcc 中按预期编译)。当编译器到达带有 n=5
的标记行时它不会为 n=4
再次编译同一行, 但只是对待 Fibo<4>::x
就好像它是用
template<> int Fibo<4>::x; // x defaults to 0
这是为什么呢?为什么在使用的时候可以正常使用
template<int n> struct Fibo { enum { x = Fibo<n-1>::x + Fibo<n-2>::x }; };
template<> struct Fibo<0> { enum { x = 1 }; };
template<> struct Fibo<1> { enum { x = 1 }; };
而不是静态变量?你如何修复第一个代码(没有 enum
)?
最佳答案
标准对此非常明确:
14.7.1 Implicit instantiation [temp.inst]
9 The implicit instantiation of a class template does not cause any static data members of that class to be implicitly instantiated.
main()
中的所有调用给你的Fibo<n>::x
对于 n > 1
, 是显式实例化,通过 Fibonnaci 递归将隐式实例化 Fibo<n-1>
和 Fibo<n-2>
但不是他们的成员x
.这意味着在这些点上,static
成员x
将被评估为其默认初始化 0
.对于 n=1
和 n=0
,编译器将看到 1 的显式初始化值。如此有效,您可以得到以下计算
Fibo<5>::x --> Fibo<4>::x + Fibo<3>::x --> 0 + 0 = 0
Fibo<4>::x --> Fibo<3>::x + Fibo<2>::x --> 0 + 0 = 0
Fibo<3>::x --> Fibo<2>::x + Fibo<1>::x --> 0 + 1 = 1
Fibo<2>::x --> Fibo<1>::x + Fibo<0>::x --> 1 + 1 = 2
Fibo<1>::x --> 1
Fibo<0>::x --> 1
您需要实例化静态成员x
在评估 Fibonacci 递归之前。您可以通过 static const int
来做到这一点或 enum
成员(member)x
,或通过 @Jarod42 所示的函数(在 C++11 中可能是 constexpr
)。
关于c++ - 递归模板不能像预期的那样使用静态变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19345033/