[C++] Templates

Templates are similar to the generic types and generic methods in C#. Using templates, it is possible to create generic functions and classes. Basic idea of templates is that you can create a logic for one type and reuse it for several different types.  

 

1. Generic Functions

A generic function is capable of overloading itself.

template <class generic_type > return_type func_name (parameter list)

  • Generic Functions are created by using the keyword “template
  • A generic function is also called a “template function
  • A compiler creates a specific version of this generic function for you. It is called a “specialization” and this specialized function is called a “generated function“.
class MyClass
{
public:
  int x;
};

template <class X> void swapfunc (X &a, X &b)
{
  X temp;
  temp = a;
  a = b;
  b = temp;
}

int main()
{
  // (1) integer
  int i = 5, j = 3;
  cout << "Before swapping : i =  " << i << ", j = " << j << endl; // 5, 3
  swapfunc(i, j);
  cout << "After swapping : i =  " << i << ", j = " << j << endl; // 3, 5

  // (2) double
  double d = 1.2, e = 3.4;
  cout << "Before swapping : d =  " << d << ", e = " << e << endl; // 1.2, 3.4
  swapfunc(d, e);
  cout << "After swapping : d =  " << d << ", e = " << e << endl; // 3.4, 1.2

  // (3) class
  MyClass obj1, obj2;
  obj1.x = 20; obj2.x = 10;
  cout << "Before swapping : obj1.x =  " << obj1.x << ", obj2.x = " << obj2.x << endl; // 20, 10
  swapfunc(obj1, obj2);
  cout << "After swapping : obj1.x =  " << obj1.x << ", obj2.x = " << obj2.x << endl; // 10, 20

  return (EXIT_SUCCESS);
}

 

2. Generic Functions with multiple Types

You can specify more than one generic types.

template <class generic_type1, class generic_type2, … > return_type func_name (parameter list)

 

3. Overloading Generic Functions

You can overload explicitly a generic function again. It is called “explicit specialization“. Moreover, you can override the “template” function itself with different parameter sets.

class MyClass
{
public:
  int x;
public:
  bool operator==(MyClass a);
  bool operator<(MyClass a);
  bool operator>(MyClass a);
};

bool MyClass::operator==(MyClass a) // overload ==
{
  if (x == a.x)
    return true;
  else
    return false;
}
bool MyClass::operator<(MyClass a) // overload <
{
  if (x < a.x)
    return true;
  else
    return false;
}
bool MyClass::operator>(MyClass a) // overload >
{
  if (x > a.x)
    return true;
  else
    return false;
}

// template function
template <class X> X getMin(X &a, X &b)
{
  cout << "inside the template function" << endl;
  // return the small one
  if ( a < b )
    return a;
  else if ( a > b )
    return b;
  else
    return a;   // a == b
}

// overload the double version of the template function
double getMin(double &a, double &b)
{
  cout << "inside the double version of the template function" << endl;
  // return the small one
  if ( a < b )
    return a;
  else if ( a > b )
    return b;
  else
    return 0;   // return 0 instead of a
}

// overload the template function
template <class X> X getMin(X &a, X &b, X &c)
{
  cout << "inside the overloaded template function" << endl;
  // return the small one
  if ( a < b )
    return a;
  else if ( a > b )
    return b;
  else
    return c;   // return c instead of a
}

int main(int argc, _TCHAR* argv[])
{
  // (1) integer
  int i = 10, j = 20, k = 5;
  cout << "call getMin(10, 20) : " << getMin(i, j) << endl; // 10
  cout << "call getMin(10, 10) : " << getMin(i, i) << endl; // 10
  cout << "call getMin(10, 10, 5) : " << getMin(i, i, k) << endl << endl; // 5

  // (2) double
  double d = 1.2, e = 3.4, f = 5.6;
  cout << "call getMin(1.2, 3.4) : " << getMin(d, e) << endl; // 1.2
  cout << "call getMin(1.2, 1.2) : " << getMin(d, d) << endl; // 0
  cout << "call getMin(1.2, 1.2, 5.6) : " << getMin(d, d, f) << endl  << endl; // 5.6

  // (3) class
  MyClass obj1, obj2, obj3;
  obj1.x = 40; obj2.x = 30; obj3.x = 20;
  cout << "call getMin(obj1 = 40, obj2 = 30) : " << (static_cast (getMin(obj1, obj2))).x << endl; // 30
  cout << "call getMin(obj1 = 40, obj1 = 40) : " << (static_cast (getMin(obj1, obj1))).x << endl; // 40
  cout << "call getMin(obj1 = 40, obj1 = 40, obj3 = 20) : " << (static_cast (getMin(obj1, obj1, obj3))).x << endl << endl; // 20

  return (EXIT_SUCCESS);
}

 

4. Generic Classes

You can create a class which uses logic that can be generalized.

template <class generic_type1> class class_name

class MyClass
{
public:
  int x;
};

template <class X> class MySimpleStack
{
private:
  int index;
  X arrStorage[100];
public:
  MySimpleStack();
  void push(X x);
  X pop();
};

template <class X> MySimpleStack::MySimpleStack() // constructor
{
  index = 0;
}
template <class X> void MySimpleStack<X>::push(X x)
{
  if ( index>=0 && index<100 )
  {
    arrStorage[index] = x;
    index++;
  }
}
template <class X> X MySimpleStack<X>::pop()
{
  if ( index>=0 && index<100 )
  {
    index--;
    return arrStorage[index];
  }
  else
  {
    arrStorage[0];
  }
}

int _tmain(int argc, _TCHAR* argv[])
{
  // (1) integer stack
  MySimpleStack  intStack;
  intStack.push(1);
  intStack.push(2);
  intStack.push(3);
  intStack.push(4);
  cout << "Pushed to the stack : 1,2,3,4  "<< endl;
  cout << "Popping : " << intStack.pop() << endl; // 4
  cout << "Popping : " << intStack.pop() << endl; // 3
  cout << "Popping : " << intStack.pop() << endl; // 2
  cout << "Popping : " << intStack.pop() << endl; // 1

  // (2) class stack
  MyClass obj1, obj2, obj3, obj4;
  obj1.x = 40; obj2.x = 30; obj3.x = 20; obj4.x = 10;
  MySimpleStack  classStack;
  classStack.push(obj1);
  classStack.push(obj2);
  classStack.push(obj3);
  classStack.push(obj4);
  cout << "Pushed to the stack : 40,30,20,10  "<< endl;
  cout << "Popping : " << (static_cast <MyClass> (classStack.pop())).x << endl; // 10
  cout << "Popping : " << (static_cast <MyClass> (classStack.pop())).x << endl; // 20
  cout << "Popping : " << (static_cast <MyClass> (classStack.pop())).x << endl; // 30
  cout << "Popping : " << (static_cast <MyClass> (classStack.pop())).x << endl; // 40

  return (EXIT_SUCCESS);
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s