When you create a function that performs an abstract operation: copying, reversing and sorting data, you must define multiple versions thereofone for each datatype. Consider a max() function which returns the higher of its two arguments:
double max(double first, double second);
complex max(complex first, complex second);
date max(date first, date second);
//..additional versions
The programmer must define a separate function for each datatype although the implementation is identical in all these cases:
double max(double first, double second)
{
return first>second? first : second;
}
complex max(complex first, complex second)
{
return first>second? first : second;
}
date max(date first, date second)
{
return first>second? first : second;
}
Not only is the reduplication of code laborious and error-prone, but it's also a fertile source of maintenance and debugging problems. Worse yet, even if you don't use every version of max() in your program, their code still increases the executable's size as most linkers will not remove an unreferenced function from the executable.

Implementing an abstract operation as an ordinary function forces you to
define multiple instances of that function, thereby incurring considerable maintenance and debugging overheads.

Use a function template instead of an ordinary function.