C++ Template Metaprogramming

Posted on Updated on

From my last entry I ended up writing this program while studying Template Metaprogramming:

#include <iostream>

template <int N> struct Factorial {
	static const int result = N * Factorial<N-1>::result;	
};

// describes a specific case of a Factorial
// We need a base case (a way to break out of the recursive loop, which in this case
// is 1)
template <> struct Factorial<0> {
	static const int result = 1;	
};


template <int N, int D> struct Frak {
	static const long Num = N;
	static const long Den = D;
};

template <int N, typename F> struct ScalarMultiplication {
	typedef Frak<N*F::Num, F::Den> result;	
};

int main() {
	typedef Frak<2, 3> Two_Thirds;
	
	typedef ScalarMultiplication<2, Two_Thirds>::result Four_Thirds;
	std::cout << Four_Thirds::Num << "/" << Four_Thirds::Den << "\n";
	return 0;
}

This looks messy but I finally figured out why the executed result is 4/3, and the reason is pretty simple but hard to notice.

Starting from Main():

int main() {
	typedef Frak<2, 3> Two_Thirds;
	
	typedef ScalarMultiplication<2, Two_Thirds>::result Four_Thirds;
	std::cout << Four_Thirds::Num << "/" << Four_Thirds::Den << "\n";
	return 0;
}

Two_Thirds is a variable type and its a method call to Frak, which is a blue print to when we call our ScalarMultiplication template.

template <int N, int D> struct Frak {
	static const long Num = N;
	static const long Den = D;
};
template <int N, typename F> struct ScalarMultiplication {
	typedef Frak<N*F::Num, F::Den> result;	
};

// somewhere in Main() ...
int main() {
         // ///	
	typedef ScalarMultiplication<2, Two_Thirds>::result Four_Thirds;
        // ...
}

N is 2, and F is 3. But looking closely at this line:

typedef Frak<N*F::Num, F::Den> result;	

Our template takes 2 parameters. 2 and 3, and the first parameter is 2 … which is then multiplied by itself to the number 4 and 3 is never calculated. So later when we print the results of this code we will get the answer 4/3

Hopefully if anybody was confused they might find this a little bit clearer … I hope…

EDIT: 2015/04/28
Thanks to nicolasbrailo for clearing up the confusion I had (my bad (d’oh!)) about Two_thirds. It’s not a variable, its a type. Check out his comment below for more details. Thanks bro! ^^
My code after modified according to Nicolas’s comment:

#include <iostream>
 
struct Two_thirds {
    static const long Num = 2;
    static const long Den = 3;
};

int main() {
    std::cout << (Two_thirds::Num*Two_thirds::Num) << "/" << Two_thirds::Den << "\n";
    return 0;
}

Much easier!

Advertisements

2 thoughts on “C++ Template Metaprogramming

    nicolasbrailo said:
    28/04/2015 at 7:27 am

    Hi Ben. Almost there!

    Two_Thirds is not actually a variable, it’s a type. Just like a class is a type. If it makes it easier to see it this way, it’s almost like a copy-paste of the class definition. In fact that may be a good way to understand what that code is doing: just copy&paste the original class definition and replace its parameters by whatever is being used to instantiate the class. In this example, “typedef Frak Two_Thirds;” is exactly as if you had written this:

    struct Two_Thirds {
    static const long Num = 2;
    static const long Den = 3;
    };

    If you do the same with the rest of the statements in main you should be able to quickly understand why it prints what it does.

      Benji responded:
      28/04/2015 at 7:46 am

      Hi Nicolas!

      Thank you so much for your comment. I modified my code as you suggested:

      struct Two_thirds {
          static const long Num = 2;
          static const long Den = 3;
      };
       
      int main() {
          std::cout << Two_thirds::Num << "/" << Two_thirds::Den << "\n";
      
          return 0;
      }
      

      And understood what you mean’t straight away! it really is much easier to think of it this way!
      Thanks also for your tutorial! Very easy to understand ^^

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s