我用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;
}
此代码输出:
$ ./a.out
Hey!
Odd!
Even!
Odd!
Even!
Odd!
Even!
Odd!
Even!
Odd!
Even!
我预测最后会调用
EvenOdd<10>::EvenOdd() //=> "Hey!"。但是,这是错误的。
为什么“嘿!”首先输出?
答案 0 :(得分:8)
此行为与模板无关。这是基本的递归。您在打印之前递归实例化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>
答案 1 :(得分:6)
您的模板EvenOdd
仅针对参数10
明确专门化,所有其他专业化的构造函数为模板参数EvenOdd
实例化匿名N+1
,作为第一个操作他们的构造者。
这意味着EvenOdd
构造函数将在任何EvenOdd
对象构造EvenOdd
对象之前递归生成匿名Print
临时对象,直到模板参数10。
构造第11个EvenOdd
对象导致输出“Hey!”,然后构造第一个Print
对象。