Function Templates
You've probably written functions where the only difference among the functions is the type of its arguments. Consider the following functions. The functions print a subinterval of a vector of doubles and a vector of integers, respectively.
void print(const vector<double>& vec, int start, int stop) {
   for (int i = start; i < stop; i++) {
      cout << vec[i] << " ";
   }
}
void print(const vector<int>& vec, int start, int stop) {
   for (int i = start; i < stop; i++) {
      cout << vec[i] << " ";
   }
}
As you can see, both functions are identical with the exception of the type of vec. It is a waste of
time and energy to rewrite such code multiple times. So, we get the compiler to do it for us. This is where function
templates come in. A function template, as its name suggest, is a template for a function. It isn't an actual function that can be compiled
into machine code. Let's write a template function that can be used to create the above functions.
template <typename T>
void print(const T& vec, int start, int stop) {
   for (int i = start; i < stop; i++) {
      cout << vec[i] << " ";
   }
}
 T is the template parameter. To make a function that can be compiled, the compiler only needs to substitute
T for an actual type. There's nothing special about the name T. We could have used
any other valid identifier. Usually the template parameter is give a logical name i.e., a name that suggests the types
we expect the template parameter to be filled by. For example, RandomIterator is a common name used
in the standard template library. The name RandomIterator tells us that the function template only works
when given a type that supports the operations that can be performed on a random access iterator. Operations such as
 ++, --, [], and so on.
A function template can be called like any other function, we can also specify the exact function we want by specifying
the template as in the following: print<vector<double>>(vec). This line of code will cause the creation
of the first function presented above. When we don't specify the template parameter, the complier infers a type based
on the arguments given to the function. If the compiler is unable to figure it out, you'll get compiler error.
Templates are a very powerful tool in C++. We are only scratching the surface. Next lab we will look at template classes.
Create a template function that takes two random access iterators start, end. It should sort all the number in the range
[start, end). Your function should work with both pointers to an array and iterators to a container that has randomaccess
iterators. Make appropriate pre/post comments. Your precomment should include the assumption that the iterators/pointers given to
the function are valid, with start <= end.
Work on Friday's assignment. Next lab we will look at class templates.