Templates
C++ 2 Outline Function templates Function template definition Function template overloading Class templates Class template definition Class template objects
C++ 3 Function templates If we would like to define a function in such a way as we should call it for different types of parameters, we can define a function template. This template contains template parameters which will be substituted with real types, when calling the function.
C++ 4 Function Template Definition We start the function definition with template where the list of parameters must be given in the form: class name_1, class name_2,..., class name_n Thus, name_i can substitute a type. The list of formal parameters of the function must contain all type parameters.
C++ 5 Example #include using namespace std; template void MySwap(T& a, T& b) { T x; x = a; a = b; b = x; }
C++ 6 The Print_Swap Function template void Print_Swap(T& a, T& b) { cout << "before swapping:\n"; cout << "a =" << a << "\t"; cout << "b =" << b << endl;
C++ 7 The Print_Swap Function MySwap(a, b); cout << "after swapping:\n"; cout << "a =" << a << "\t"; cout << "b =" << b << endl; }
C++ 8 The main Function int main() { int u = 3; int v = 5; Print_Swap(u, v); double y = 3.2; double z = 5.7; Print_Swap(y, z); }
C++ 9 Output before swapping: a =3 b =5 after swapping: a =5 b =3 before swapping: a =3.2 b =5.7 after swapping: a =5.7 b =3.2
C++ 10 Example 2 #include using namespace std; template void Display_Type(T a) { cout << a << "\t"; cout << typeid(T).name() << endl; }
C++ 11 The Fraction Class class Fraction { int numerator; int denominator; public: Fraction(int a, int b); ostream& Display(ostream &s) const; };
C++ 12 Constructor Fraction::Fraction(int a, int b) { numerator = a; denominator = b; }
C++ 13 The Display Function ostream& Fraction::Display(ostream &s) const { return s << numerator << " / " << denominator; }
C++ 14 Inserter Operator Overloading ostream& operator <<(ostream& s, const Fraction & t) { return t.Display(s); }
C++ 15 The main Function int main() { Display_Type(3); Display_Type(5.9); Fraction y(4, 9); Display_Type(y); }
C++ 16 Output 3 int 5.9 double 4 / 9 class Fraction
C++ 17 Function Template Overloading If we don’t want to generate an issue of the function template for a specific list of parameters, then we can overload the function template. This should be done by adding a conventional function to the code, which has exactly the required list of parameters.
C++ 18 Example (MySwap) #include using namespace std; //...
C++ 19 MySwap template void MySwap(T& a, T& b) { T x; x = a; a = b; b = x; cout << "With function template\n"; }
C++ 20 Allow Different Types template void Print_Swap(T1& a, T2& b) { cout << "before swapping:\n"; cout << "a =" << a << "\t"; cout << "b =" << b << endl; MySwap(a, b); cout << "after swapping:\n"; cout << "a =" << a << "\t"; cout << "b =" << b << endl; }
C++ 21 Overloading void MySwap(int& a, double& b) { int x; x = a; a = static_cast (b); b = x + fabs(b-a); cout << "Without a template\n"; }
C++ 22 The main function void main() { double y = 3.2; double z = 5.7; Print_Swap(y, z); int t = 7; double w = 10.9; Print_Swap(t, w); }
C++ 23 Output before swapping: a =3.2 b =5.7 With function template after swapping: a =5.7 b =3.2 before swapping: a =7 b =10.9 Without a template after swapping: a =10 b =7.9 Change only integer parts
C++ 24 Class Template Definition Definition: template class ClassName { //... }; The list of parameters can contain type parameters and constant parameters. The type parameters should be given in the form class name and the constant parameters as an ordinary declaration, in the form type name.
C++ 25 Member Function Definition If the member functions are defined outside the class, then these should be function templates. Thus, they should start with: template After the class name we should give only the parameter names between the signs.
C++ 26 Example (member function) template class MyStack { T t[I]; public: //... void Push(T x); }; template void MyStack ::Push(T x){ //... }
C++ 27 Objects of the Class Template When defining an object, after the class name one has to give the type parameters and the constant parameters. Use the following form: classname object; Example: MyStack v;
C++ 28 Example Define the MyStack class template, with the Push and Pop member functions, and overload the inserter << operator such that all the elements should be take out from the stack. #include using namespace std;
C++ 29 The MyStack Class Template template class MyStack { T t[I]; int n; public: class FullStack {}; // exception
C++ 30 The MyStack Class Template class EmptyStack{}; //exception MyStack() { n = 0; } void Push(T x); T Pop(); ostream& Pop_Print(ostream& s); };
C++ 31 The Push Member Function template void MyStack ::Push(T x) { if ( n == I ) throw FullStack(); t[n++] = x; }
C++ 32 The Pop Member Function template T MyStack ::Pop() { if ( n == 0 ) throw EmptyStack(); return t[--n]; }
C++ 33 The Pop_Print Member Function template ostream& MyStack ::Pop_Print (ostream& s) { while(n > 0) s << t[--n] << " "; return s << endl; }
C++ 34 The Inserter Operator template ostream& operator & v) { return v.Pop_Print(s); }
C++ 35 The first main function (10 elements of type int) int main() { const int dim = 10; MyStack v; for(int i = 0; i < dim; i++) v.Push(i); cout << v; } Output:
C++ 36 The second main function (5 elements of type double) int main() { const int dimension = 5; MyStack v2; for(int i = 0; i < dimension; i++) v2.Push(i + static_cast (i) / 10); cout << v2; } Output:
C++ 37 The third main function (full stack) int main() { const int dim = 10; MyStack v; try { for(int i = 0; i <= dim; i++) v.Push(i); } catch( MyStack ::FullStack ) { cout << "The stack is full.\n"; } The stack is full. Output:
C++ 38 The last main function (empty stack) int main() { const int dim = 10; MyStack v; for(int i = 0; i < dim; i++) v.Push(i); try { while( true)cout << v.Pop() << " "; } catch( MyStack ::EmptyStack ) { cout << "Empty.\n"; } Empty. Output: