Saturday 28 January 2017

Templates - C++ Tutorials

Function templates

Function templates are special functions that can operate with generic types. This allows us to create a function template whose functionality can be adapted to more than one variable type or class without repeating the code for each type.
This is achieved through template parameters. A template parameter is a special kind of parameter that can be used to pass a type as parameter. These function templates can use these parameters as if they were regular types.
The format for declaring function templates with type parameters is:
template <class identifier> function_declaration;
template <typename identifier> function_declaration;
The only difference between both prototypes is the use of either the keyword class or the keyword typename. Its use is indistinct since both expressions have exactly the same meaning and behave exactly the same way.
For example, to create a template function that returns the greater one of two objects we could use:
template <class myType>
myType GetMax (myType a, myType b) {
 return (a>b?a:b);
}
Here we have created a template function with myType as its template parameter. This template parameter represents a type that has not yet been specified, but that can be used in the template function as if it were a regular type. As you can see, the function template GetMax returns the greater of two parameters of this still-undefined type.
To use this function template we use the following format for the function call:
function_name <type> (parameters);
For example, to call GetMax to compare two integer values of type int we can write:
int x,y;
GetMax <int> (x,y);
When the compiler encounters this call to a template function, it uses the template to automatically generate a function replacing each appearance of myType by the type passed as the actual template parameter (int in this case) and then calls it. This process is automatically performed by the compiler and is invisible to the programmer.
Here is the entire example:
// function template
#include <iostream>
using namespace std;
 
template <class T>
T GetMax (T a, T b) {
  T result;
  result = (a>b)? a : b;
  return (result);
}
 
int main () {
  int i=5, j=6, k;
  long l=10, m=5, n;
  k=GetMax<int>(i,j);
  n=GetMax<long>(l,m);
  cout << k << endl;
  cout << n << endl;
  return 0;
}
6
10
In this case we have used T as the template parameter name instead of myType because it is shorter and in fact is a very common template parameter name. But you can use any identifier you like.
In the example above we used the function template GetMax() twice. The first time with arguments of type int and the second one with arguments of type long. The compiler has instantiated and then called each time the appropriate version of the function.
As you can see, the type T is used within the GetMax() template function even to declare new objects of that type:
T result;
Therefore, result will be an object of the same type as the parameters a and b when the function template is instantiated with a specific type.
In this specific case where the generic type T is used as a parameter for GetMax the compiler can find out automatically which data type has to instantiate without having to explicitly specify it within angle brackets (like we have done before specifying <int> and <long>). So we could have written instead:
int i,j;
GetMax (i,j);
Since both i and j are of type int, and the compiler can automatically find out that the template parameter can only be int. This implicit method produces exactly the same result:
// function template II
#include <iostream>
using namespace std;
 
template <class T>
T GetMax (T a, T b) {
  return (a>b?a:b);
}
 
int main () {
  int i=5, j=6, k;
  long l=10, m=5, n;
  k=GetMax(i,j);
  n=GetMax(l,m);
  cout << k << endl;
  cout << n << endl;
  return 0;
}
6
10
Notice how in this case, we called our function template GetMax() without explicitly specifying the type between angle-brackets <>. The compiler automatically determines what type is needed on each call.
Because our template function includes only one template parameter (class T) and the function template itself accepts two parameters, both of this T type, we cannot call our function template with two objects of different types as arguments:
int i;
long l;
k = GetMax (i,l); 
This would not be correct, since our GetMax function template expects two arguments of the same type, and in this call to it we use objects of two different types.
We can also define function templates that accept more than one type parameter, simply by specifying more template parameters. For example:
template <class T, class U>
T GetMin (T a, U b) {
  return (a<b?a:b);
}
In this case, our function template GetMin() accepts two parameters of different types and returns an object of the same type as the first parameter (T) that is passed. For example, after that declaration we could call GetMin() with:
int i,j;
long l;
i = GetMin<int,long> (j,l);
or simply:
i = GetMin (j,l);
even though j and l have different types. But the compiler can determine the apropriate instantiation anyway.

 

Class templates

We also have the possibility to write class templates, so that a class can have members that use template parameters as types. For example:
template <class T>
class pair {
    T values [2];
  public:
    pair (T first, T second)
    {
      values[0]=first; values[1]=second;
    }
};
The class that we have just defined serves to store two elements of any valid type. For example, if we wanted to declare an object of this class to store two integer values of type int with the values 115 and 36 we would write:
pair<int> myobject (115, 36); 
this same class would also be used to create an object to store any other type:
pair<float> myfloats (3.0, 2.18); 
The only member function in the previous class template has been defined inline within the class declaration itself. In case that we define a function member outside the declaration of the class template, we must always precede that definition with the template <...> prefix:
// class templates
#include <iostream>
using namespace std;
template <class T>
class pair {
    T a, b;
  public:
    pair (T first, T second)
      {a=first; b=second;}
    T getmax ();
};
template <class T>
T pair<T>::getmax ()
{
  T retval;
  retval = a>b? a : b;
  return retval;
}
int main () {
  pair <int> myobject (100, 75);
  cout << myobject.getmax();
  return 0;
}
100
Notice the syntax of the definition of member function getmax:
template <class T>
T pair<T>::getmax () 
Confused by so many T's? There are three T's in this declaration. The first one is the template parameter. The second T refers to the type returned by the function. And the third T (the one between angle brackets) is also a requirement. It specifies that this function's template parameter is also the class template parameter.

Template specialization

If we want to define a different implementation for a template when a specific type is passed as template parameter, we can declare a specialization of that template.
For example, let's suppose that we have a very simple class called container that can store one element of any type and that it has just one member function called increase, that increases its value. But we find that when it stores an element of type char it would be more convenient to have a completely different implementation with a function member uppercase, so we decide to declare a class template specialization for that type:
// template specialization
#include <iostream>
using namespace std;
 
template <class T>
class container {
    T element;
  public:
    container (T arg) {element=arg;}
    T increase () {return ++element;}
};
 
template <>
class container <char> {
    char element;
  public:
    container (T arg) {element=arg;}
    char uppercase ();
};
 
template <>
char container<char>::uppercase()
{
  if ((element>='a')&&(element<='z'))
  element+='A'-'a';
  return element;
}
 
int main () {
  container<int> myint (7);
  container<char> mychar ('j');
  cout << myint.increase() << endl;
  cout << mychar.uppercase() << endl;
  return 0;
}
8
J
This is the syntax used in the class template specialization:
template <> class container <char> { ... };
First of all, notice that we precede the class template name with template<>. This is a requirement in standard C++ for all template specializations, although some compilers, as an anachronism, support to declare template specialization without this prefix.
But more important than this prefix, is the <char> specialization parameter after the class template name. This specialization parameter itself identifies the type for which we are going to declare a template class specialization (char). Notice the differences between the generic class template and the specialization:
template <class T> class container { ... };
template <> class container <char> { ... };
The first line is the generic template, and the second one is the specialization.
When we declare specializations for a template class, we must also define all its members, because there is no inheritance of members from the generic template to the specialization.

Non-type parameters for templates

Besides the template arguments that are preceded by the class or typename keywords , which represent types, templates can also have regular typed parameters, similar to those found in functions. As an example, have a look at this class template that is used to contain sequences of elements:
// sequence template
#include <iostream>
using namespace std;
 
template <class T, int N>
class sequence {
    T memblock [N];
  public:
    void setmember (int x, T value);
    T getmember (int x);
};
 
template <class T, int N>
void sequence<T,N>::setmember (int x, T value) {
  memblock[x]=value;
}
 
template <class T, int N>
T sequence<T,N>::getmember (int x) {
  return memblock[x];
}
 
int main () {
  sequence <int,5> myints;
  sequence <double,5> myfloats;
  myints.setmember (0,100);
  myfloats.setmember (3,3.1416);
  cout << myints.getmember(0) << '\n';
  cout << myfloats.getmember(3) << '\n';
  return 0;
}
100
3.1416 
It is also possible to set default values or types for class template parameters. For example, if the previous class template definition had been:
template <class T=char, int N=10> class sequence {..};
We could create objects using the default template parameters by declaring:
sequence<> myseq;
Which would be equivalent to:
sequence<char,10> myseq;

Templates and multiple-file projects

From the point of view of the compiler, templates are not normal functions or classes. They are compiled on demand, meaning that the code of a template function is not compiled until an instantiation with specific template arguments is required. At that moment, when an instantiation is required, the compiler generates a function specifically for those arguments from the template.
When projects grow it is usual to split the code of a program in different source code files. In these cases, the interface and implementation are generally separated. Taking a library of functions as example, the interface generally consists of declarations of the prototypes of all the functions that can be called. These are generally declared in a "header file" with a .h extension, and the implementation (the definition of these functions) is in an independent file with c++ code.
Because templates are compiled when required, this forces a restriction for multi-file projects: the implementation (definition) of a template class or function must be in the same file as its declaration. That means that we cannot separate the interface in a separate header file, and that we must include both interface and implementation in any file that uses the templates.

Since no code is generated until a template is instantiated when required, compilers are prepared to allow the inclusion more than once of the same template file with both declarations and definitions in a project without generating linkage errors. 

Friday 27 January 2017

Polymorphism - C++ Tutorials

Before getting into this section, it is recommended that you have a proper understanding of pointers and class inheritance. If any of the following statements seem strange to you, you should review the indicated sections:
Statement:
Explained in:
int a::b(c) {};
Classes
a->b
Pointers
class a: public b;
Friendship and inheritance

 

Pointers to base class

One of the key features of derived classes is that a pointer to a derived class is type-compatible with a pointer to its base class. Polymorphism is the art of taking advantage of this simple but powerful and versatile feature, that brings Object Oriented Methodologies to its full potential.
We are going to start by rewriting our program about the rectangle and the triangle of the previous section taking into consideration this pointer compatibility property:
// pointers to base class
#include <iostream>
using namespace std;
 
class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
  };
 
class CRectangle: public CPolygon {
  public:
    int area ()
      { return (width * height); }
  };
 
class CTriangle: public CPolygon {
  public:
    int area ()
      { return (width * height / 2); }
  };
 
int main () {
  CRectangle rect;
  CTriangle trgl;
  CPolygon * ppoly1 = &rect;
  CPolygon * ppoly2 = &trgl;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  cout << rect.area() << endl;
  cout << trgl.area() << endl;
  return 0;
}
20
10
In function main, we create two pointers that point to objects of class CPolygon (ppoly1 and ppoly2). Then we assign references to rect and trgl to these pointers, and because both are objects of classes derived from CPolygon, both are valid assignations.
The only limitation in using *ppoly1 and *ppoly2 instead of rect and trgl is that both *ppoly1 and *ppoly2 are of type CPolygon* and therefore we can only use these pointers to refer to the members that CRectangle and CTriangle inherit from CPolygon. For that reason when we call the area() members at the end of the program we have had to use directly the objects rect and trgl instead of the pointers *ppoly1 and *ppoly2.
In order to use area() with the pointers to class CPolygon, this member should also have been declared in the class CPolygon, and not only in its derived classes, but the problem is that CRectangle and CTriangle implement different versions of area, therefore we cannot implement it in the base class. This is when virtual members become handy:

Virtual members

A member of a class that can be redefined in its derived classes is known as a virtual member. In order to declare a member of a class as virtual, we must precede its declaration with the keyword virtual:
// virtual members
#include <iostream>
using namespace std;
 
class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area ()
      { return (0); }
  };
 
class CRectangle: public CPolygon {
  public:
    int area ()
      { return (width * height); }
  };
 
class CTriangle: public CPolygon {
  public:
    int area ()
      { return (width * height / 2); }
  };
 
int main () {
  CRectangle rect;
  CTriangle trgl;
  CPolygon poly;
  CPolygon * ppoly1 = &rect;
  CPolygon * ppoly2 = &trgl;
  CPolygon * ppoly3 = &poly;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  ppoly3->set_values (4,5);
  cout << ppoly1->area() << endl;
  cout << ppoly2->area() << endl;
  cout << ppoly3->area() << endl;
  return 0;
}
20
10
0
Now the three classes (CPolygon, CRectangle and CTriangle) have all the same members: width, height, set_values() and area().
The member function area() has been declared as virtual in the base class because it is later redefined in each derived class. You can verify if you want that if you remove this virtual keyword from the declaration of area() within CPolygon, and then you run the program the result will be 0 for the three polygons instead of 20, 10 and 0. That is because instead of calling the corresponding area() function for each object (CRectangle::area(), CTriangle::area() and CPolygon::area(), respectively), CPolygon::area() will be called in all cases since the calls are via a pointer whose type is CPolygon*.
Therefore, what the virtual keyword does is to allow a member of a derived class with the same name as one in the base class to be appropriately called from a pointer, and more precisely when the type of the pointer is a pointer to the base class but is pointing to an object of the derived class, as in the above example.
A class that declares or inherits a virtual function is called a polymorphic class.
Note that despite of its virtuality, we have also been able to declare an object of type CPolygon and to call its own area() function, which always returns 0.

Abstract base classes

Abstract base classes are something very similar to our CPolygon class of our previous example. The only difference is that in our previous example we have defined a valid area() function with a minimal functionality for objects that were of class CPolygon (like the object poly), whereas in an abstract base classes we could leave that area() member function without implementation at all. This is done by appending =0 (equal to zero) to the function declaration.
An abstract base CPolygon class could look like this:
// abstract class CPolygon
class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area () =0;
};
Notice how we appended =0 to virtual int area () instead of specifying an implementation for the function. This type of function is called a pure virtual function, and all classes that contain at least one pure virtual function are abstract base classes.
The main difference between an abstract base class and a regular polymorphic class is that because in abstract base classes at least one of its members lacks implementation we cannot create instances (objects) of it.
But a class that cannot instantiate objects is not totally useless; We can create pointers to it and take advantage of all its polymorphic abilities. Therefore a declaration like:
CPolygon poly;
would not be valid for the abstract base class we have just declared, because tries to instantiate an object. Nevertheless, the following pointers:
CPolygon * ppoly1;
CPolygon * ppoly2;
would be perfectly valid.
This is so for as long as CPolygon includes a pure virtual function and therefore it's an abstract base class. However, pointers to this abstract base class can be used to point to objects of derived classes.
Here you have the complete example:
// abstract base class
#include <iostream>
using namespace std;
 
class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area (void) =0;
  };
 
class CRectangle: public CPolygon {
  public:
    int area (void)
      { return (width * height); }
  };
 
class CTriangle: public CPolygon {
  public:
    int area (void)
      { return (width * height / 2); }
  };
 
int main () {
  CRectangle rect;
  CTriangle trgl;
  CPolygon * ppoly1 = &rect;
  CPolygon * ppoly2 = &trgl;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  cout << ppoly1->area() << endl;
  cout << ppoly2->area() << endl;
  return 0;
}
20
10
If you review the program you will notice that we refer to objects of different but related classes using a unique type of pointer (CPolygon*). This can be tremendously useful. For example, now we can create a function member of the abstract base class CPolygon that is able to print on screen the result of the area() function even though CPolygon itself has no implementation for this function:
// pure virtual members can be called
// from the abstract base class
#include <iostream>
using namespace std;
 
class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area (void) =0;
    void printarea (void)
      { cout << this->area() << endl; }
  };
 
class CRectangle: public CPolygon {
  public:
    int area (void)
      { return (width * height); }
  };
 
class CTriangle: public CPolygon {
  public:
    int area (void)
      { return (width * height / 2); }
  };
 
int main () {
  CRectangle rect;
  CTriangle trgl;
  CPolygon * ppoly1 = &rect;
  CPolygon * ppoly2 = &trgl;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  ppoly1->printarea();
  ppoly2->printarea();
  return 0;
}
20
10
Virtual members and abstract classes grant C++ the polymorphic characteristics that make object-oriented programming such a useful instrument in big projects. Of course, we have seen very simple uses of these features, but these features can be applied to arrays of objects or dynamically allocated objects.
Let's end with the same example again, but this time with objects that are dynamically allocated:
// dynamic allocation and polymorphism
#include <iostream>
using namespace std;
 
class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area (void) =0;
    void printarea (void)
      { cout << this->area() << endl; }
  };
class CRectangle: public CPolygon {
  public:
    int area (void)
      { return (width * height); }
  };
class CTriangle: public CPolygon {
  public:
    int area (void)
      { return (width * height / 2); }
  };
 
int main () {
  CPolygon * ppoly1 = new CRectangle;
  CPolygon * ppoly2 = new CTriangle;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  ppoly1->printarea();
  ppoly2->printarea();
  delete ppoly1;
  delete ppoly2;
  return 0;
}
20
10
Notice that the ppoly pointers:
CPolygon * ppoly1 = new CRectangle;
CPolygon * ppoly2 = new CTriangle;

are declared being of type pointer to CPolygon but the objects dynamically allocated have been declared having the derived class type directly.