我用C++模板写了偶数/奇数的判断代码.
#include <iostream>
template <int N, int Mod2=N%2>
struct Print {
Print() {
std::cout << N << std::endl;
}
};
template <int N>
struct Print<N, 0> {
Print() {
std::cout << "Even!" << std::endl;
}
};
template <int N>
struct Print<N, 1> {
Print() {
std::cout << "Odd!" << std::endl;
}
};
template <int N>
struct EvenOdd {
EvenOdd() {
EvenOdd<N+1>();
Print<N>();
}
};
template <>
struct EvenOdd<10> {
EvenOdd() {
std::cout << "Hey!" << std::endl;
}
};
int main()
{
EvenOdd<0>();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码输出:
$ ./a.out
Hey!
Odd!
Even!
Odd!
Even!
Odd!
Even!
Odd!
Even!
Odd!
Even!
Run Code Online (Sandbox Code Playgroud)
我预测到了
EvenOdd<10>::EvenOdd() //=> "Hey!"最后被称为.但是,这是错误的.
为什么"嘿!" 首先输出?
此行为与模板无关.这是基本的递归.您EvenOdd
在打印前递归实例化.因此,打印任何东西的第一个实例是最里面的,即EvenOdd<10>
.
这是发生了什么:首先EvenOdd<0>
做的是实例化EvenOdd<1>
.只有完成后才会调用Print<0>
.直到EvenOdd<1>
完成实例化EvenOdd<2>
和打印后才能完成,依此类推:
EvenOdd<0>
EvenOdd<1>
EvenOdd<2>
EvenOdd<3>
EvenOdd<4>
EvenOdd<5>
EvenOdd<6>
EvenOdd<7>
EvenOdd<8>
EvenOdd<9>
EvenOdd<10>
std::cout << "Hey!" << std::endl;
Print<9>
Print<8>
Print<7>
Print<6>
Print<5>
Print<4>
Print<3>
Print<2>
Print<1>
Print<0>
Run Code Online (Sandbox Code Playgroud)
您的模板EvenOdd
仅显式专用于参数10
,所有其他特化的构造函数EvenOdd
将模板参数的匿名实例化N+1
为其构造函数中的第一个操作.
这意味着EvenOdd
构造函数将EvenOdd
在任何EvenOdd
对象构造Print
Object 之前以递归方式生成直到模板参数10的匿名临时对象.
构造第11个EvenOdd
对象导致输出"Hey!",然后Print
构造第一个对象.