Lecture Notes for Advanced Programming II

26 March 2002 - Template Functions


  1. polymorphism - abstraction with respect to types.

    1. how many elements in a list is independent of element type

  2. templates - explicit type abstraction

    1. warning - templates were crammed into c++

      1. syntax is disgusting

      2. compile-time behavior can be confusing

      3. determining feature interaction can be difficult

  3. function templates

    1. precede the function with template <class T1, ...>

    2. each Ti is called a template paramter; can represent any type, not just a class

    3. can also use typename

    4. use each of the template parameters Ti as if it were a type spec

    5. the compiler matches a template-function call with the defined template parameters

      1. the function names must match

      2. the actual argument types must match exactly the formal parameter types

        1. f(1, 1.0) does not match
          template <class t1,class t2>f(t1 a1, t2 a2) { . . . }

      3. there must be exactly one matching template-function definition

      4. the return value is not used to match templates

    6. template <class t>
      inline t max(t v1, t v2) {
        return v1 > v2 ? v1 : v2;
        }
      
      void fint(int x, int y) {
        int m = max(x, y);
        }
      
      void fdbl(double x, double y) {
        double m = max(x, y);
        }
      
      void fstr(std::string & x, std::string & y) {
        std::string m = max(x, y);
        }
      

    7. integral template parameter values are allowed
      template<int size>
      void t(int i) {
        int iarray[size];
        iarray[i] = i;
        }
      
      int main() {
        t<10>(3);
        }
      

  4. gotchas

    1. the compiler looks only at function arguments to determine types

      1. each Ti must appear as an argument type - otherwise the compiler can't determine Ti's type.
        template <class t>
        t * oops(int i) {
          i++;
          return new t;
          }
        
        void f(void) {
        int * ip = oops(1);
        }
        

      2. explicit template initialization is possible to overcome this problem
        void f(void) {
          int * ip = oops(1);
          }
        

    2. type matching is strict - there is no conversion

      1. template <class t>
        void oops(t i, t j) {
          // whatever
          }
        
        void f(void) {
          int i = 3;
          unsigned j = 4;
          oops(i, j)
          }
        

      2. consts are another source of problems, particularly in the stl

    3. watch the operations performed on template-type values - they must be defined

    4. interactions with function overloading, function pointers, ...


This page last modified on 26 March 2002.