如何使用C++模板理解输出结果

use*_*120 3 c++ templates

我用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!"
最后被称为.但是,这是错误的.

为什么"嘿!" 首先输出?

jal*_*alf 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>
Run Code Online (Sandbox Code Playgroud)


CB *_*ley 6

您的模板EvenOdd仅显式专用于参数10,所有其他特化的构造函数EvenOdd将模板参数的匿名实例化N+1为其构造函数中的第一个操作.

这意味着EvenOdd构造函数将EvenOdd在任何EvenOdd对象构造PrintObject 之前以递归方式生成直到模板参数10的匿名临时对象.

构造第11个EvenOdd对象导致输出"Hey!",然后Print构造第一个对象.