Understanding Template Programming in C++ : Part 2
In this tutorial we will apply our knowledge of templates from Part 1 and create a generic class that can accept any acceptable data type.
Function Template :
First we will see a function called addition that takes two numbers as argument.
int add(int firstNum, int secondNum)
{
return firstNum + secondNum;
}
Now, if we want to have the same function taking different data type for the arguments, we would require to replicate the same function definition with the different data type, which would create duplicate code.
double add(double firstNum, double secondNum)
{
return firstNum + secondNum;
}
To resolve this, we introduce templates -
template <typename T>
T add(T firstNum, T secondNum)
{
return firstNum + secondNum;
}
This template definition specifies a family of functions that return the addition of two values, which are passed as function parameters firstNum and secondNum. The type of these parameters is left open as template parameter T.
Now to use this function, we simple provide the data type while calling it.
int main()
{
std::cout << add<int>(3, 7) << std::endl; // Call add for int
std::cout << add<double>(3.0, 7.0) // Call add for double
return 0;
}
In our example, the list of parameters is typename T.
Note how the < and > are used as brackets (referred as angle brackets). The keyword typename introduces a type parameter.
Class Template :
Class templates make the class generic by simplifying the existing code, reducing duplicate entries.
Here, we will create a class Calculator, which will have two member variables and two member functions namely, addition and subtraction.
class Calculator
{
private:
int firstNum, secondNum;
public:
Calculator(int first, int second) : firstNum(first), secondNum(second) {}
int addition { return (firstNum + secondNum); }
int subtraction { return (firstNum - secondNum); }
};
Now, if we want to add or subtract any other numerical data type than float, we would require to re-write the class and function for each required data. This will lead to duplication.
We use class templates in such cases —
template <class T>
class Calculator
{
private:
T firstNum, secondNum;
public:
Calculator(T first, T second) : firstNum(first), secondNum(second) {}
T addition { return (firstNum + secondNum); }
T subtraction { return (firstNum - secondNum); }
};
This will make our class generic and enable it to work with any applicable data type.
int main()
{
Calculator<int> CalcIntObj(25, 12);
Calculator<float> CalcFloatObj(13.6, 5.9);
std::cout << "Integer addition : " << CalcIntObj.addition() << std::endl;
std::cout << "Float addition : " << CalcFloatObj.addition() << std::endl;
std::cout << "Integer Subtraction: " << CalcIntObj.subtraction() << std::endl;
std::cout << "Float Subtraction: " << CalcFloatObj.subtraction() << std::endl;
return 0;
}
Class Templates with Multiple Parameters :
There may come a situation where there are more than one data types required by the function/class and both of those requiring different data types.
In such cases, templates can also be applied easily. Below is the implementation of class with multiple parameters -
template <class T, class U>
class Display
{
private:
T firstNum;
U secondNum;
public:
Display(T first, Usecond) : firstNum(first), secondNum(second) {}
void show()
{
std::cout << "The inputs are : " << firstNum << " and " << secondNum << std::endl;
}
};
int main()
{
Display<int, float> dispObj(27, 81.99);
dispObj.show();
return 0;
}
Advantages of using Templates :
- Templates are type-safe.
- They are usually considered to be an improvement over macros for these purposes.
- They provide a better way for making generalizations for APIs.