Templates in C++

C++ Templates

C++ Templates represent a technique of generic programming that allows you to create generic functions and classes that can work with different data types. It’s a powerful mechanism of C++ used to develop generic code to perform actions with objects of various kinds.

The following problem can lead to the necessity to use templates: “You have to write a program that will be able to get maximum of two elements for the following data types: int, short int, long int, double, float.”

You can write different functions for every type. It is the worst solution. Also, you can overload a function for different parameters and return type. It is a little bit better, but still, you will need to write a large amount of code that has the same behavior.

Syntax of Function Template

The best solution for this task is to write a function template that will work with all these types.

Function template can be created by using the template keyword. The declaration of a function the template has syntax as follows:

template <parameter list> function-declaration

The parameter list is the list of types that are used in this template. These parameters can be set in the form as:

Class identifier

template<class T>
void myFunc()
{
}

typename identifier

template<typename T>
void myFunc()
{
}

template<parameter list> class identifier

class foo
{
};
template<template<typename T> class T>
void myFunc()
{
}

A non type parameter

template<class T, int i>
void myFunc()
{
}

In the first two cases, class and typename are keywords that are used to specify the parameters of the function template. The third one describes the possibility to use a template class as a parameter to another template. The last one represents a possibility to use value instead of a type in the parameter list.

Example of Function template

The declaration and definition of the function template that has to return the maximum of two numbers look in the following way:

template <typename T>
T max(T a, T b)
{
	return a > b ? a : b;
}

This declaration means that a template function with name max is created. The parameter of this the template is named as T. When you will call this function and specify the argument of the template, T will be replaced with the specified type everywhere in the function.

Use of Function template

You can call now function max with different types that have operator >:

//calling max with int parameters
cout << "Maximum of 3 and 5 is " << max(3, 5) << endl;
//calling max with double parameters
cout << "Maximum of 4.2 and 4.7 is " << max(4.2, 4.7) << endl;

As you can see, in this example, template function allows only to get maximum of the elements of the same type, because in the parameter list both a and b parameters are of the type T. The return type is the same as the type of the compared elements.

Explicit Instantiation

When you use the same type for both parameters of a function template, the compiler will deduct parameter type automatically. However, you can compare elements of different types. In this case, you have to instantiate template function explicit by specifying the parameter list in the call.

For example, we can compare an integer with a double. The integer value will be cast to double when the template argument is specified:

//explicit instantiation
cout << "Maximum of 7.36 and 7 is " << max<double>(7.36, 7) << endl;

The template class or function is not a type or an object. It is just a blueprint for creating a specified function or class. If your code has only a template definition – no additional code will be generated. Nevertheless, when you use a function template or a class template and specify its
parameters – the compiler will make the actual function (class) with specified types.

For example, the code above will generate two functions that will return the maximum of two integers and a maximum of two double values:

int max(int a, int b)
{
	return a > b ? a : b;
}
double max(double a, double b)
{
	return a > b ? a : b;
}

You will not see this code in your source files, but this is the mechanism that is used by templates.

Multiple Parameters Template

The parameter list can include different types. These types have to be comma-separated and have different identifiers. For example, we can create a template function that will output two values of different types:

template<typename T1, typename T2>
void output(T1 obj1, T2 obj2)
{
	cout << "Obj1 is " << obj1 << ". Obj2 is " << obj2 << endl;
}

Here, two different types of T1 and T2 are used as parameters.

Class template

The class template is a blueprint that is used to generated different classes according to the parameter list. Often, class templates are used to implement containers. The declaration of a class template is similar to the declaration of function template:

template<parameter list>
class class-identifier

Important note

The declaration and definition of template member functions must be done in the same header file. The standard technique to separate class declaration and definition into the header (.h) and source file (.cpp) is not applicable for the class template.

Class Template Example

In the previous topics, we examined the Stack class, which was an example of a stack of integer values.

class myStack {
  public:
    //allocate memory for stack
    myStack(int _size = 50) {
      size = _size;
      stack = new int[size];
      //initially stack is empty
      top = -1;
    }
  //add value to stack
  bool push(int i) {
    if (isFull())
      return false;
    else {
      top++;
      stack[top] = i;
    }
  }
  int pop() {
    if (isEmpty())

      throw new exception("Stack is empty");
    else {
      return stack[top--];
    }
  }
  private:
    //return true if stack is full
    bool isFull() {
      return size == top - 1;
    }
  bool isEmpty() {
    return top == -1;
  }
  int size;
  int * stack;
  int top;
};

This class works only with integer values. It would be advantageous if we had a template class that implements functions of the stack data structure for the objects of different types.

We can do it by using the template class. For this purpose, we have to modify the class declaration by adding the template parameter list. All the object of the stack class have the same type, so parameter list consists of only one parameter:

template <typename T>
class myStack

Now we want to store the elements of the type T in the stack. For this purpose, stack pointer, the parameter of the push function and the return type of the pop function should be of the type T. We can modify it quickly and now use stack class of any type:

template <typename T>
class myStack {
  public:
    //allocate memory for stack
    myStack(int _size = 50) {
      size = _size;
      //memory is allocated for type T
      stack = new T[size];
      //initially stack is empty
      top = -1;
    }
  //add value of Type T to stack
  bool push(T i) {
    if (isFull())
      return false;
    else {
      top++;
      stack[top] = i;
    }
  }
  //element of type T is returned
  T pop()

  {
    if (isEmpty())
      throw new exception("Stack is empty");
    else {
      return stack[top--];
    }
  }
  private:
    //return true if stack is full
    bool isFull() {
      return size == top - 1;
    }
  bool isEmpty() {
    return top == -1;
  }
  int size;
  //elements of type T are stored
  T * stack;
  int top;
};

If you want to instantiate an object of the stack type, you have to determine explicit the types of stored elements:

//list of ints
myStack<int> intStack(10);
//list of doubles
myStack<double> doubleStack(20);
//list of chars
myStack<char> charStack(5);

Default values for the parameter list

There is a possibility to specified the default value for the parameters of the template. It can be done in the template declaration:

template<typename T1 = defaultType, typename T2 = defaultType, …>
class class-identifier

For example, the default value for the stack class can be set to int:

template <typename T = int>
class myStack

In this case, if you do not instantiate template explicit, int stack will be created by default:

//list of ints created by default
myStack<> intStack(10);

As you can see, templates allow increasing the possibilities of created classes. It is a very powerful instrument for generic programming. C++ offers a large number of class and function templates that are collected into Standard Template Library (STL).STL is discussed in details in “C++ STL Tutorial”

Translate »