tags:

views:

128

answers:

3

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 <>
struct 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?

+6  A: 

Your template EvenOdd is explicitly specialized for the parameter 10 only, all other specializations' constructors instantiate an anonymous EvenOdd for the template parmeter 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.

Charles Bailey
+7  A: 

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>
jalf
+3  A: 

For a better understanding of TMP(Template Metaprogramming) read this.

You may also refer to the book

C++ Templates: The Complete Guide By David Vandevoorde, Nicolai M. Josuttis

Prasoon Saurav
They're both good books, but this doesn't answer the question...
jon hanson
The answers were already provided.
Prasoon Saurav
This should've been a comment.
int3
I'll take care of this next time. :)
Prasoon Saurav