What are templates?

C++ templates are functions that can handle different data types without writing separate code for each of them. To perform a similar operation on several kinds of data types, a programmer need not write different versions by overloading a function. Instead the programmer can write a C++ template based function that will work with all data types.

There are two types of templates in C++, function templates and class templates. First off we will examine function templates.

Function Templates

There are many occasions where we might need to write the same functions for different data types. A simple example can be the addition of two variables, for example, of the int, float or double types. The function requirement will be to return the summed value with the correct return type that is based on the type of the input variables. If we start writing one function for each of the data types, then we will end up with 4 to 5 different functions, that all contain very similar code. This goes against everything we have learned so far in OOP.

C++ templates are a useful facility in these situations. When we use C++ function templates, only one function "signature" needs to be created. The C++ compiler will automatically generate the required functions for handling the individual data types. This makes programming much easier - Here is an example:

An Example: Here is a short example of an add() function. If the requirement is to use this add() function for both int and float types, then two functions are to be created, one for each of the data types (over-loading).

  int add(int a,int b) { return a+b;} // function without using function templates
  float add(float a, float b) { return a+b;} // function without using function templates

If there were more data types to be handled, more functions would have to be added. Using C++ function templates for this task makes the entire process a lot easier, by reducing the code to a single C++ function template. Here is the function template code for the same add() functions.

 template <class T>  //The class keyword here means any 
                           //standard OR user-defined type
 T add(T a, T b)           //C++ function template example
 {
   return a+b;
 }

Now as before, logically this example is a bit simplistic as the "+" operator does the same thing, but it is a good start. C++ function templates can be used wherever the same functionality has to be performed with a number of data types. Though very useful, experience tells us that lots of care should be taken to test the C++ template functions during development. A well written C++ template will go a long way in saving time.

Templates are different than classes though, When you instantiate a template the compiler has to see its definition before it can generate its source code. The usual approach is to define the entire template in a header file and then #include it in every source file that uses this template i.e. do not separate the template into a .h and .cpp file. This brings up an (arguably) interesting point, since a class template must be in a header file it means that the source code is always exposed, even if you are selling your product to an untrusted client.

Class Templates

Class templates are often used to build type safe containers. Class templates allow us to create a class that works with/on any user-defined class (type), so the obvious application is for advanced storage. This functionality is provided by C++ Class templates, also called parameterized types, and the technique is called generic programming. Here is a short example of a made up class called Storage that provides basic storage of user-defined types:


  // First Template Example
  // by Derek Molloy - Template Example
  
  #include<iostream>
  using namespace std;
  
  template<class T>
  class Storage
  {
    T values[100]; // can store 100 values of type T (quite basic)
    
    public:
      T& operator [](int index)
      {
        return values[index];
      }
    };
    
    int main()
    {
      Storage<int>   intArray;
      Storage<float> floatArray;
      
      for (int i=0; i<10; i++)
      {
        intArray[i] = i * i;
        floatArray[i] = (float)i/2.1234 ; 
      }
      
      for (int i=0; i<10; i++)
      {
        cout << " intArray value   = " <<   intArray[i] 
          << " floatArray value = " << floatArray[i] << endl; 
      }
    }

The full source code for this example is listed in ClassTemplates1.cpp

This first example is a little basic as it is fixed to contain only 100 elements of the user-defined type. We can remove this hard coding, by rewriting the code to:

  // Second Template Example
  // by Derek Molloy - More advanced Template Example.
  
  #include<iostream.h>
  using namespace std;
  
  template<class T, int size>
  class Storage
  {
    T values[size]; // can store size values of type T
    
    public:
      T& operator [](int index)
      {
        return values[index];
      } 
    };
    
    int main()
    {
      Storage<int,10> intArray;
      Storage<float,20> floatArray;
      
      for (int i=0; i<10; i++)
      {
        intArray[i] = i * i;
        floatArray[i] = (float)i/2.1234 ; 
      }
      
      for (int i=0; i<10; i++)
      {
        cout << " intArray value = " << intArray[i] 
          << " floatArray value = " << floatArray[i] << endl;
      }
    }

The full source code for this example is listed in ClassTemplates2.cpp

That is not quite everything to do with templates:

  • Inheritance: Class templates can inherit properties from other class templates or even non-templates.

  • Friends: We can use friend functions with templates

  • Static: A class template can have static members, but these static members are shared amongst each specialization of the class template. For example, if you had a class template as above and you used it for int and float then there would be one static member for the int specialization and the float specialization.