开发者

How to understand the result of output with C++ templates

I wrote a judgment code of even/odd numbers with C++ templates.

#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 <>
struc开发者_如何学运维t EvenOdd<10> {
  EvenOdd() {
    std::cout << "Hey!" << std::endl;
  }
};

int main()
{
  EvenOdd<0>();
  return 0;
}

This code outputs:

$ ./a.out
Hey!
Odd!
Even!
Odd!
Even!
Odd!
Even!
Odd!
Even!
Odd!
Even!

I predicted that

EvenOdd<10>::EvenOdd() //=> "Hey!"
is called lastly. But, it's mistake.

Why does "Hey!" output firstly?


This behavior has nothing to do with templates specifically. It is basic recursion. You recursively instantiate EvenOdd before printing. And so the first instance to print anything is the innermost, which is EvenOdd<10>.

Here's what happens: the first thing EvenOdd<0> does is to instantiate EvenOdd<1>. Only when that completes, does it call Print<0>. And that doesn't complete until EvenOdd<1> has finished instantiating EvenOdd<2> and printed, and so on:

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>


Your template EvenOdd is explicitly specialized for the parameter 10 only, all other specializations' constructors instantiate an anonymous EvenOdd for the template parameter N+1 as the first action in their constructor.

This means that the EvenOdd constructor will recursively generate anonymous EvenOdd temporary objects up to the template parameter 10 before any EvenOdd object constructs a Print Object.

Constructing the 11th EvenOdd object results in outputting "Hey!", then the first Print object is constructed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜