我用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 ::EvenOdd()//=>“嘿!”最后被调用。但是,这是错误的。

为什么会“嘿!”首先输出?

最佳答案

此行为与模板无关。这是基本的递归。您在打印之前递归实例化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>

09-20 00:09