Templates

The min function

  1. Here is a set of functions in main.C that should be written as a template function. The C++ Standard library already has a function named min whose full name is std::min because it belongs to the standard namespace std. The full name of my min functions is ::min, because they do not belong to any namespace. I wrote ::min to make sure I was calling my own min functions, not the one in the standard library.

    To get the expression b < a to compile when b and a are of data type const date&, I had to define the functions operator< or operator int for class date.

    	if (b < a) {       //if operator<(b, a) {
    
    	if (b < a) {       //if (b.operator int() < a.operator int()) {
    
    1. date.h: a very simple class date, just enough to make the main function work.
    2. date.C
    3. main.C, main.txt
    c++ main.C date.C
    
  2. Let’s declare and define a function template in main.C that will work for every data type except const char *.

    The first three calls to min in the main function create three instantiations of the function template. In the three instantiations, the computer deduces that the T should be changed to int, double, double, const date& respectively. (An instantiation is also called an implicit specialization.)

    The T is called a template argument. As usual, the a and b are called function arguments. And the 10 and 20 are the actual function arguments.

    1. date.h: exactly the same class date as in the previous example.
    2. date.C
    3. main.C, main.txt: exactly the same main function as in the previous program, but the rest of main.C is different.
    c++ main.C date.C
    
  3. Combine the function declarations and definitions in main.C.
    1. date.h: exactly the same class date as in the previous example.
    2. date.C
    3. main.C, main.txt: exactly the same main function as in the previous example, but the rest of main.C is different.
    c++ main.C date.C
    
  4. Move the function declarations and definitions to a .h (header) file.
    1. min.h contains the declarations and definitions of the min template function. See the important comment about the data type T.
    2. date.h: exactly the same class date as in the previous example.
    3. date.C
    4. main.C, main.txt: exactly the same main function as in the previous example, but the rest of main.C is different.
    c++ main.C date.C
    
    10
    2.71
    5/1/2025
    goodbye
    
    See this min.h for a better version that passes function arguments of type T by reference, i.e., as a const T&.
    Ths shows that the data type of a function argument can be more than just a plain unadorned T.
  5. The min in the C++ Standard Library does not know that the data type const char * probably needs to be handled differently.
    1. date.h: exactly the same class date as in the previous example.
    2. date.C
    3. main.C, main.txt calls the min function in the C++ Standard Library.

More than one template argument: T1 and T2

  1. Each print function has two arguments, which may be of different data types.
    1. date.h: exactly the same class date as in the previous example.
    2. date.C
    3. main.C, main.txt
    c++ main.C date.C
    
  2. A template function can have more than one template argument.
    1. print.h contains the template
    2. date.h: exactly the same class date as in the previous example.
    3. date.C
    4. main.C, main.txt
    c++ main.C date.C
    

A local variable of type T

  1. Three different swap functions:
    1. date.h: exactly the same class date as in the previous example.
    2. date.C
    3. main.C, main.txt
    c++ main.C date.C
    
  2. A template function containing a local variable of type const T:
    1. date.h: exactly the same class date as in the previous example.
    2. date.C
    3. swap.h contains the template
    4. main.C, main.txt
    c++ main.C date.C
    
    #include <algorithm> for the C++ Standard Library swap.

An explicit template argument

  1. The second call to our min template will not compile, because our min template requires two actual arguments of the same data type. In this case, the computer is unable to deduce which data type, int or double, the T should turn into.
    1. min.h
    2. main.C
    c++ main.C
    
    main.C: In function ‘int main()’:
    main.C:14:22: error: no matching function for call to ‘min(int&, double&)’
       14 |         cout << ::min(i, d) << "\n";   //won’t compile
          |                 ~~~~~^~~~~~
    

    An explicit template argument is also required when the template function takes no function arguments at all. In this case, the return value of f<double> has one more correct digit than the return value of f<float>. That’s ten times as accurate!

    1. pi.C, pi.txt
    c++ -std=c++20 pi.C
    

A template class

  1. A class point with double data members:
    1. point.h: member functions and friends, inline and not inline
    2. point.C
    3. main.C, main.txt
    c++ main.C point.C
    
  2. The same class point with float data members. On our machine storm.cis.fordham.edu, a float occupies only half as many bytes as a double.
    1. point.h: member functions and friends, inline and not inline
    2. point.C
    3. main.C, main.txt
    c++ main.C point.C
    
  3. A template class point. There is no more point.C file.
    1. point.h: member functions and friends, inline and not inline
    2. main.C, main.txt
    c++ main.C
    

A template class with a static member function

  1. Class counted is not a template class. It has a static member function named count which receives no invisible argument.
    1. counted.h
    2. counted.C
    3. main.C, main.txt
    c++ main.C counted.C
    
  2. Class numeric_limits is a template class with two static member functions, min and max.
    1. main.C, main.txt
    c++ main.C
    
    We will never create any object of classes numeric_limits<int>, numeric_limits<long>, etc. The only purpose of these classes is to give us information about the data types int, long, etc. Other examples of classes that give us information about other data types are char_traits and iterator_traits.

All the Standard Library container classes are template classes.

  1. Class vector is a template class. (See vectorint.C and vectordouble.C.) Ditto for classes list and set.
    1. main.C, main.txt
    c++ main.C
    
  2. Class map is a template class with two template arguments.
    1. map.C, map.txt
    c++ map.C
    

A numeric template argument

  1. Older C++ said typedef, but contemporary C++ says using.
    1. using.C, using.txt
    c++ using.C
    
  2. Each atom contains an array of electrons and an array of protons.
    1. hydrogen_atom.h
    2. helium_atom.h
    3. oxygen_atom.h
    4. main.C, main.txt
  3. Mass produce the elements with one template class.
    1. atom.h
    2. main.C, main.txt
  4. Hide the template with the keyword using. The person who makes a hydrogen object will never suspect that hydrogen is a template class.
    1. atom.h
    2. main.C, main.txt

Templates and Inheritance

  1. Remove the three nearly identical position-in-the foodchain classes carnivore, herbivore, inert from the game. Instead of #include’ing the three header files carnivore.h, herbivore.h, inert.h in the header files for the four grandchild classes wolf.h, rabbit.h, boulder.h, landmine.h, simply #include the following header file position.h in the header files for the four grandchild classes.
    1. position.h
    cc -DUNIX= -c term.c
    ls -l term.o
    
    c++ main.C wabbit.C terminal.C term.o -lcurses
    ls -l a.out
    
    ./a.out
    
  2. Remove the four nearly identical grandchild classes wolf, rabbit, boulder, landmine from the game. Instead of #include’ing the two header files wolf.h and rabbit.h in main.C, simply #include the following header file grandchild.h in main.C.
    1. grandchild.h

    Invent another new class of grandchild called a looseCannon that moves randomly (like a rabbit) and has the appetite of a carnivore (like a wolf). On the screen, a loose cannon will appear as the character c.

    Have main.C create grandchildren of all these different classes. With the 3 motion and 3 rank classes we already have, we could easily create 3 × 3 = 9 classes of grandchildren.
    cc -DUNIX= -c term.c
    ls -l term.o
    
    c++ main.C wabbit.C terminal.C term.o -lcurses
    ls -l a.out
    
    ./a.out