[C++]Function Templates

[C++]Function Templates

Function Templates

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;
}