Skip to Content
Author's profile photo Preethi Natarajan

Beginner’s Guide to C++ Templates – 2

I am back with the next part on the guide. In the previous post I asked you to practice by writing a simple function template which prints the double of the number specified. Here is the code for that.


template<typename Type>
void printDouble(Type num)
{
cout<<(num * 2);
}
int main()
{
    printDouble(5);
    printDouble(1.3);
    printDouble(2.4f);
}

Let us revisit the template we wrote for add and learn some technical C++ details needed behind the scene for it to compile and run. I am introducing it now because after having written and executed two templates we now are no longer averse to templates…and also these features are of C++ So I might be stating the obvious.


template<typename T>
T add(T n1, T n2)
{
     T res;
     res = n1 + n2;
     return res;
}

The compiler does two rounds of compilation. In the first round it checks for syntax, proper usage of keywords, semi-colons, bracket matching. In the second round of compilation, the compiler does for the specific datatype that is invoked. This is a concept called as “On demand compilation”.

For the add function the compiler checks

  1. Does Type T have a default constructor? This is for the declaration T res to be a valid statement.
  2. Does the type T support the use of operator+ ? This is for the line n1 + n2 to be valid.
  3. Does the type T have a copy constructor? This is for the return statement to be valid.

Now let us see another code sample. This code is that of shell sort. It is one of the sorting techniques for in-place comparison sort. It does sorting by insertion and sorting by exchange. Here is the code for it.



template<typename T>
void shell_sort(T arr[], int num)
{
     int i,j,inc;
     T temp = T();
     for(inc = num/2; inc > 0; inc /= 2)
     {
           for(i=inc;i<num;i++)
           {
                 temp = arr[i];
                for(j=i;j>=inc;j=j-inc)
                {
                     if(temp < arr[j-inc])
                     arr[j] = arr[j-inc];
                else
                     break;
                 }
                 arr[j] = temp;
           }
      }
}

Some of the use cases for this function template


int array_i[5]={44,45,32,36,16};
shell_sort(array_i,5);
float array_f[6] = {11.3f, 34.4f, 3.0f,2.3f, 4.3f, 1.1f};
shell_sort(array_f,6);
char array_c[7] = { 'c', 'e' , 'g', 't', 'w', 'a', 'd'};
shell_sort(array_c,7);
double array_d[3] = {33.4, 11.2, 0.3};
shell_sort(array_d,3);

The results of these calls are


16 32 36 44 45
1.1 2.3 3 4.3 11.3 34.4
a c d e g t w
0.3 11.2 33.4

Things to notice in the shell sort template.

  • It is ok to have template and non-template arguments in the template function call. Notice that the interface takes a template type T array and an integer as its input parameters.
  • Next thing to note here is that array is mentioned as just type T and not as array T[] or as pointer T*.  The compiler will deduce it as an array of integers or of floats or of chars or of doubles.
  • Third thing to note here is that in the code a temporary variable is needed which stores the value of the ith iteration array entry before the next iteration. Since the array is a template type, a need arises that the temporary variable also to be of the same template type. This is where the line T temp = T() is called. Please know that this is a C++ requirement. That is T should have a default constructor and the basic data types we have used so far all have default constructors. If T is a user defined type then the default constructor of the user defined type will be invoked.

If the shell sort template was defined with the pointer notation ( T* ) instead of the T[] array notation, the compiler would still understand it as a array or as an address of a variable T. So we can safely use T* and T[] notations interchangeably. This logic is valid in C and hence it is an inherent C++ property.

If there is a need to use reference like in this simple example


template<template T>
void double_the_num(T& num)
{
     T temp_res = T();
     temp_res = num + num;
     num = temp_res;
}

T& works the same way as int& or double&. This example calculates twice the value of what is passed and puts the doubled value into the same argument value.


int number = 4;
double_the_num(number); //after the call the variable number has value 8

Here in this example I have used the operator + to double to number. We can use the other loaded operators like operator+= or operator*= to achieve the same result. For simple data types this is provided by the data type but for UDTs(User Defined Type or simply classes) and complex data types one has to check if the class has these operators defined and then use it while writing a template intended to be used for that UDT.

So now that we have the knowledge on how to write function templates by using arrays, pointers to array and references, let us attempt to write another simple template. Write a template to get the average of some numbers and another template that gets the median of some numbers. Median is simply the middle element of a sorted array. In case of even number in the array we take the mean of the middle two elements for the sorted array.

Go ahead and write these two templates. In case you don’t have a fully downloaded and ready to use compiler and editor on your system, there are many on-line compilers that will help you write simple programs. Go ahead and use on of them for your programming and learning.

See you next time. Until then Happy Programming!

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.