Templates in C++ can basically be referred to as blueprints that can be used to make specialized functions and classes.
There are class templates and function templates, I will be focusing on function templates today
It allows you to write "one" specialized version of a function that works for most data types(int, double, float and even user defined classes) without needing to write the same function for different data types. e.g:
int sum(int a, int b){
return a +b;
}
double sum(double a, double b){
return a +b;
}
Assuming you had to write a function that takes the sum of two values that works with different data types, normally you would have to write multiple copies of the same function but with the different data type as it's return value and argument, but with templates you can write that function once and the compiler will generate a specialized version that works with the data type you need, this is how it would be done:
template<typename S> \\ you can write either typename or class, they generally do the same thing
S sum(S a, S b){
return a + b;
}
If you don't write the template you'll be using i.e template<typename S>
, the compiler won't generate any code and you'll run into errors because it doesn't know what S is.
Note: you can use other letters and words as your template placeholder('S'), i just used 'S' because i felt like doing so
Now with that template function written, the compiler can generate specialized versions depending on the data type you use as the arguments, Lets see how we would call it if we wanted to calculate the sum of two integers and doubles
int a1{2};
int a2{3};
int a3 = sum<int>(a1, a2); // a3 becomes 5
double d1{1.2};
double d2{0.8};
double d3 = sum<double>(d1, d2); //d3 becomes 3
You can see how easy the template function made one function able to work with different data types without having to duplicate the same function multiple times, also in most cases the compiler is smart enough to figure out what data type is passed into the function without you telling it when calling the function <int>, <double>
, you can write int a3 = sum(a1, a2);
and the compiler would know figure out by itself that it's an integer.
WORKING WITH USER DEFINED CLASSES
If we wanted to use that same 'sum' function with a class we defined ourselves, it wouldn't work out of the box like that because it's not a primitive data type(int, double, float, string) that the compiler knows, Lets say we have a class called Student:
class Student{
public:
int data;
std::string temp;
Student(){
data = 0;
temp = "Default";
}
Student(int d, std::string t){
data = d;
temp = t;
}
};
Assuming we want to use the sum
function with our class
Student a(16, "Padawan");
Student b(15, "Hermes");
Student c = sum<Student>(a, b);
//or
std::cout << sum<Student>(a, b) << std::endl;
we'll run into an error because the sum function adds the two arguments passed into it and the compiler won't know what the addition of two Student object is unlike with ints and other primitive data types, so to make the compiler able to know what the addition of two Student
object is, we have to overload the + operator. (operator overloading is a way to make operators like +, <<, >>, =,==, work with our user defined class, you can see more info here).
//class with overloaded operator
class Student{
friend Student operator+(const Student &lhs, const Student &rhs);
public:
int data;
std::string temp;
//no -arguments constructor
Student(){
data = 0;
temp = "Default";
}
//arguments contructor
Student(int d, std::string t){
data = d;
temp = t;
}
};
Student operator+(const Student &lhs, const Student &rhs){
Student temp;
temp.data = lhs.data + rhs.data;
return temp;
}
I overloaded the + operator for the Student
class in such a way that when two Student objects are added together, their data object is added together, Now our Student
class will work with the + operator. If we were to call the sum
function with our Student class it would add their int data
objects together and return a Student
object with that exact sum, (You'll have to define a no-argument constructor for your class if you want this entire process to work because the sum function is returning a default Student object that is created with no arguments). Now if we have something like:
int main(){
Student t(4, "Herm");
Student k(6, "Perv");
Student b = sum(t, k); // or sum<Student>(t, k);
std::cout << b.data << std::endl; //outputs 10
return 0;
}
We would get a clean compile if we run this program because we've effectively made the + operator( which is what the sum
function uses) to work with our class, Thanks for Reading.
Here is the full source code for the class and stuff in case you want to copy it into your IDE and mess around:
template<typename T>
T sum(T a, T b){
return a + b;
}
class Student{
friend Student operator+(const Student &lhs, const Student &rhs);
public:
int data;
std::string temp;
Student(){
data = 0;
temp = "Default";
}
Student(int d, std::string t){
data = d;
temp = t;
}
};
Student operator+(const Student &lhs, const Student &rhs){
Student temp;
temp.data = lhs.data + rhs.data;
return temp;
}
int main(){
Student t(4, "Herm");
Student k(6, "Perv");
Student b = sum(t, k);
cout << b.data<< endl;
return 0;
}