In C every function has to have a unique name. For example: fma, fmaf, fmal
1 2 3
|
double fma (double x , double y , double z);
float fmaf (float x , float y , float z);
long double fmal (long double x, long double y, long double z);
|
All three do the same operation, but differ on the type of data that they operate on: double, float, long double.
If you have to change the type of data, then you have to update the function names everywhere in your code.
In C++ there is more to the name; the type of function arguments is part to the name. We can call all three functions 'fma':
1 2 3
|
double fma (double x , double y , double z);
float fma (float x , float y , float z);
long double fma (long double x, long double y, long double z);
|
When the C++ encounters
fma(a,b,c)
it looks at the types of the a,b,c in order to decide which 'fma' implementation to use. If you now change the types of a,b,c, the code can still compile; the compiler selects different, more appropriate 'fma'.
Multiple functions seem to have same name, because they all have 'fma'. That is overloading.
A template in a more generic instruction for the compiler to generate code for us.
Have you written a sort algorithm? Did you have to exchange values of two objects? Did it look like:
1 2 3
|
int temp = a;
a = b;
b = temp;
|
Would it be handy -- if you have to "swap values" in many places -- to have it as a function:
1 2 3 4 5 6
|
void swap ( int & a, int & b )
{
int temp = a;
a = b;
b = temp;
}
|
But ... that only swaps integers. I need to sort floats, doubles, and strings too! Do I have to copy-edit a gazillion (overloaded) versions of 'swap'? What if I invent a new way to do those three assignments ... update all versions? No way.
We can create a template:
1 2 3 4 5 6 7
|
template <class T>
void swap ( T & a, T & b )
{
T temp = a;
a = b;
b = temp;
}
|
If we now write:
1 2 3 4
|
std::map<std::string,std::vector<int>> x;
std::map<std::string,std::vector<int>> y;
// fill the maps with data
swap( x, y );
|
The compiler will write for us:
1 2 3 4 5 6
|
void swap( std::map<std::string,std::vector<int>> & a, std::map<std::string,std::vector<int>> & b )
{
std::map<std::string,std::vector<int>> temp = a;
a = b;
b = temp;
}
|
and then attempt to compile it. The compiler understands that it is handling templates and can thus give (somewhat) specific error messages.
Some day we might decide that
1 2 3 4 5 6 7
|
template <class T>
void swap ( T& a, T& b )
{
T c( std::move(a) );
a = std::move(b);
b = std::move(c);
}
|
is much more nice. No other edits required.