A C++ template metaprogram is a program which is written that executes inside the C++ compiler. The final results are computed during compilation stage using templates instantiation.
TMP has 2 main benefits:
- It shifts some computation from runtime to compiletime, thus making the program more reliable
- It improves overall runtime.
However, the consequence is that compile time will increase will increase as more computation is being done at compile time.
Following program computes value of recursion using function templates:
#include <iostream> //main header
using namespace std; //namespace
template<int N>
int GetFactorial()
{
return N * GetFactorial<N-1>();
}
template<>
int GetFactorial<1>()
{
return 1;
}
int main()
{
cout << GetFactorial<4>() << endl;
return 0;
}
Please note: Here the template instantiations at compile time achieve the recursion. This is not same as regular regular recursion which happens at execution time. A regular recursion happens using standard stack calls and there is no stack here.
A template specialization terminates the recursion. This specialization handles the ending case.
In the above program, the compiler executes “GetFactorial<4>( )” in compile time and the result “24” (a constant value) replaces the original expression. The following code is exactly equivalent to program above.
#include <iostream> //main header
using namespace std; //namespace
int main()
{
cout << 24 << endl;
return 0;
}
TMP with class templates
Class template achieve the same behavior as in the example above. This class make use of enum values. The enum values are evaluated at compile time and the caller just refers to this using scope-resolution operator. The advantage with this approach is that the program do not need to create any class object to instantiate the templates.
#include <iostream> //main header
using namespace std; //namespace
template<int N>
class GetFactorial
{
public:
enum
{
val = N * GetFactorial<N-1>::val
};
};
template<>
class GetFactorial<1> //Specialization
{
public:
enum
{
val = 1
};
};
int main()
{
cout << "The result is : "
<< GetFactorial<4>::val
<< endl;
return 0;
}
Alternate implementation with class templates
The class may also use static constant variables to achieve the same behavior as it was with enum. Such constant values shall also get evaluated at compile-time and resultant value replaces the original expression. The static keyword ensures that there is no need to instantiate the class object. Therefore, directly using scope-resolution operator, the result will get available.
#include <iostream> //main header
using namespace std; //namespace
template<int N>
class GetFactorial
{
public:
static const int val = N * GetFactorial::val;
};
template<>
class GetFactorial<1> //Specialization
{
public:
static const int val = 1;
};
int main()
{
cout << "The result is : "
<< GetFactorial<4>::val
<< endl;
return 0;
}
Implementation of design patterns
Users can implement policy-based design using Template meta programming. This concept can implement design patterns like Strategy, Observer, Visitor, etc. It’s possible to create templates representing choices also known as policies.