|< C++ Templates 1 | Main | C++ Characters & Strings 1 >| Site Index | Download |


 

MODULE 24a

THE C++ TEMPLATES - AN INTRODUCTION TO STL 2

This type, that type, so many types,

No more type! THE GENERIC TYPES

 

My Training Period: xx hours

 

C++ abilities that should be acquired:

 

         Able to understand and use Class Template.

         Able to understand and use Template instantiation.

         Able to understand and use explicit and implicit instantiation.

         Able to understand and use Template Specialization.

         Able to understand and use Template Partial Specialization.

         Able to understand and use the keyword typename.

 

 

 

 

 

24.4  Class Template Instantiation

  • A template instantiation is a process of instantiate a real class from a template for our real usage.  It provides general class template with potentially infinite data types.

  • The following is a program example of a class template instantiation.  It is bundled in one program, one file for our study convenience.

#include <iostream>

using namespace std;

 

// class template declaration part

// test.h

template <class any_data_type>

class Test

{

public:

// constructor

Test();

// destructor

~Test();

// function template

any_data_type Data(any_data_type);

};

 

template <class any_data_type>

any_data_type Test<any_data_type>::Data(any_data_type Var0)

{return Var0;}

 

// a class template definition part

// should be in the same header file with the class template declaration

// constructor

template <class any_data_type>

Test<any_data_type>::Test()

{cout<<"Constructor, allocate..."<<endl;}

 

// destructor

template <class any_data_type>

Test<any_data_type>::~Test()

{cout<<"Destructor, deallocate..."<<endl;}

 

// the main program

int main()

{

Test<int> Var1;

Test<double> Var2;

Test<char> Var3;

Test<char*> Var4;

cout<<"\nOne template fits all data type..."<<endl;

cout<<"Var1, int = "<<Var1.Data(100)<<endl;

cout<<"Var2, double = "<<Var2.Data(1.234)<<endl;

cout<<"Var3, char = "<<Var3.Data('K')<<endl;

cout<<"Var4, char* = "<<Var4.Data("The class template")<<"\n\n";

return 0;

}

 

Output:

 

C++ templates programming - a class template

#include <iostream>

using namespace std;

 

// a class template declaration part

// test.h file

template <class any_data_type>

class Test

{

public:

// constructor

Test();

// destructor

~Test();

// function template

any_data_type Data(any_data_type);

};

 

template <class any_data_type>

any_data_type Test<any_data_type>::Data(any_data_type Var0)

{return Var0;}

 

// a class template definition part

// should be in the same header file with the class template declaration

// a constructor

template <class any_data_type>

Test<any_data_type>::Test()

{cout<<"Constructor, allocate..."<<endl;}

 

// a destructor

template <class any_data_type>

Test<any_data_type>::~Test()

{cout<<"Destructor, deallocate..."<<endl;}

// do not run this program

// make sure there is no error such as typo etc

// test.cpp file

// compile and run this program

// the main program

int main()

{

Test<int> Var1;

Test<double> Var2;

Test<char> Var3;

Test<char*> Var4;

cout<<"\nOne template fits all data type..."<<endl;

cout<<"Var1, int = "<<Var1.Data(100)<<endl;

cout<<"Var2, double = "<<Var2.Data(1.234)<<endl;

cout<<"Var3, char = "<<Var3.Data('K')<<endl;

cout<<"Var4, char* = "<<Var4.Data("The class template")<<"\n\n";

return 0;

}

 

Output:

 

C++ class template program example

#include <iostream>

using namespace std;

 

template <class any_data_type>

class Test

{

    public:

         // a constructor

         Test(){ };

         // a destructor

         ~Test(){ };

         // member function templates...

         any_data_type Funct1(any_data_type Var1)

         {return Var1;}

         any_data_type Funct2(any_data_type Var2)

         {return Var2;}

};

 

// do some testing

int main()

{

// implicit instantiation generates class Test<int>...

Test<int> Var1;

// implicit instantiation generates class Test<double>...

Test<double> Var2;

 

cout<<"Implicit instantiation..."<<endl;

// and generates function Test<int>::Funct1()

cout<<"Var1 = "<<Var1.Funct1(200)<<endl;

// and generates function Test<double>::Funct2()

cout<<"Var2 = "<<Var2.Funct2(3.123)<<endl;

return 0;

}

 

Output:

 

C++ templates program - implicit instantiation of a class template

#include <iostream>

using namespace std;

 

template <class any_data_type>

class Test

{

    public:

       // a constructor

       Test(){ };

       // a destructor

       ~Test(){ };

       // a member functions...

       any_data_type Funct1(any_data_type Var1)

       {return Var1;}

       any_data_type Funct2(any_data_type Var2)

       {return Var2;}

};

 

// explicit instantiation of class Test<int>

template class Test<int>;

// explicit instantiation of class Test<double>

template class Test<double>;

 

// do some testing

int main()

{

    Test<int> Var1;

    Test<double> Var2;

    cout<<"Var1 = "<<Var1.Funct1(200)<<endl;

    cout<<"Var2 = "<<Var2.Funct2(3.123)<<endl;

    return 0;

}

 

Output:

 

C++ template programming - an explicit instantiation of a class template

 

24.5  Function Template Instantiation

// implicit instantiation

#include <iostream>

using namespace std;

 

template <class any_data_type>

any_data_type MyMax(any_data_type Var1, any_data_type Var2)

{

       return Var1 > Var2 ? Var1:Var2;

}

 

// do some testing

int main()

{

    int p;

    char q;

    p = MyMax(100, 200);

    q = MyMax('k', 'K');

    // implicit instantiation of MyMax(int, int)

    cout<<"MyMax(100, 200) = "<<p<<endl;

    // implicit instantiation of MyMax(char, char)

    cout<<"MyMax('k', 'K') = "<<q<<endl;

    return 0;

}

 

Output:

 

C++ STL implicit instantiation of function templates

 

// an explicit instantiation

#include <iostream>

using namespace std;

 

template <class any_data_type>

any_data_type Test(any_data_type Var1)

{

       return Var1;

}

 

// an explicit instantiation of Test(int)

template int Test<int>(int);

 

// do some testing

int main()

{

cout<<"Var1 = "<<Test(100)<<endl;

return 0;

}

 

Output:

 

C++ template programming - an explicit instantiation of function templates

#include <iostream>

using namespace std;

 

template <class any_data_type>

class TestVirt

{

    public:

       virtual any_data_type TestFunct(any_data_type Var1)

       {return Var1;}

};

 

// do some testing

int main()

{

    // implicit instantiation of TestVirt<int>

    TestVirt<int> Var1;

    cout<<"Var1.TestFunct(100) = "<<Var1.TestFunct(100)<<endl;

    return 0;

}

 

Output:

 

C++ template programming - instantiating the virtual member functions

 

24.6  Class Template Specialization

  • A specialization consists of a template name followed by a list or arguments in angle brackets and it is a specialize class template instantiation.

  • When we instantiate the class template, from a general class template, we make the class template special to suit our specific programming tasks.

  • A specialization can be used exactly like any other normal class and here, compiler will generate a specialized concrete instance from the generic of the templates.  For examples:

// an object instantiation

Vector<int> Var;

// as function parameter

int Funct(Vector <float>&);

// used in sizeof expression

size_t p = sizeof(Vector <char>);

// used in class object instantiations

class MyTestVector: private Vector<std::string>

{ };

Vector <Date> Var1;

Vector <string> Var2;

  • The compiler actually instantiates only the necessary member functions of a given specialization or generate when there is a request.

 

24.7  The Primary, Partial and Specialization Class Template

#include <iostream>

#include <string>

using namespace std;

 

template <class any_data_type>

inline any_data_type MyMax(const any_data_type& Var1, const any_data_type& Var2)

{

    cout<<"Checking..."<<endl;

    return Var1 < Var2 ? Var2 : Var1;

}

 

// do some testing

int main()

{

    int Highest = MyMax(7, 20);

    char p = MyMax('x' , 'r');

    string Str1 = "Class", Str2 = "Template";

    string MaxStr = MyMax(Str1, Str2);

   

    cout<<"The bigger between 7 and 20 is "<<Highest<<endl;

    cout<<"The bigger between 'x' and 'r' is "<<p<<endl;

    cout<<"The bigger between \""<<Str1<<"\" and \""<<Str2<<"\" is "<<MaxStr<<"\n\n";

    const char *Var3 = "Class";

    const char *Var4 = "Template";

    const char *q = MyMax(Var3, Var4);

    cout<<"Logical error, comparing the pointer, not the string..."<<endl;

    cout<<"Address of the *Var3 = "<<&Var3<<endl;

    cout<<"Address of the *Var4 = "<<&Var4<<endl;

    cout<<"The bigger between \""<<Var3<<"\" and \""<<Var4<<"\" is "<<q<<endl;

    cout<<"Need specialization here..."<<endl;

    return 0;

}

 

Output:

 

C++ STL class template primary and specialization program example

 

24.7.1  Implementing The Specialization

#include <iostream>

#include <string>

// for strcmp()

#include <cstring>

using namespace std;

 

// primary template, for all type

template <class any_data_type>

any_data_type MyMax(const any_data_type Var1, const any_data_type Var2)

{

       cout<<"Primary template..."<<endl;

       return Var1 < Var2 ? Var2 : Var1;

}

 

// specialization for const char *, empty parameter list

template <>

const char *MyMax(const char *Var1, const char *Var2)

{

       cout<<"Specialization..."<<endl;

       // comparison for const char *

       return (strcmp(Var1, Var2)<0) ? Var2 : Var1;

}

 

// do some testing

int main()

{

    // call primary

    int Highest = MyMax(7, 20);

    // call primary

    char p = MyMax('x' , 'r');

    string Str1 = "Class", Str2 = "Template";

    // call primary

    string MaxStr = MyMax(Str1, Str2);

    cout<<"The bigger between 7 and 20 is "<<Highest<<endl;

    cout<<"The bigger between 'x' and 'r' is "<<p<<endl;

    cout<<"The bigger between \""<<Str1<<"\" and \""<<Str2<<"\" is "<<MaxStr<<"\n\n";

    // call specialization

    const char *Var3 = "Class";

    const char *Var4 = "Template";

    const char *q = MyMax(Var3, Var4);

    cout<<"The bigger between \""<<Var3<<"\" and \""<<Var4<<"\" is "<<q<<endl;

    return 0;

}

 

Output:

 

C++ STL class template specialization program example

 

24.7.2  Partial Specialization

#include <iostream>

using namespace std;

 

// general, justice for all type:-)

template <class any_data_type>

any_data_type Test(any_data_type Var1)

{return Var1;}

 

// partial specialization for all pointers type

template <class any_data_type>

any_data_type * Test(any_data_type *Var2)

{return Var2;}

 

// specialization, just for const char *

template <>const char * Test(const char *Var3)

{return Var3;}

 

// do some testing

int main()

{

    int p = 5;

    // calls Test(any_data_type

    int q = Test(p);

    double r = Test(3.1234);

    cout<<"General types = "<<q<<endl;

    cout<<"General types = "<<r<<endl;

    // calls Test(any_data_type*)

    int *s = Test(&p);

    char *t = "Partial lor!";

    cout<<"Partial types = "<<s<<endl;

    cout<<"Partial types = "<<t<<endl;

    // calls Test(const char *)

    const char *u = Test("Specialized!");

    cout<<"Specialization type = "<<u<<endl;

    return 0;

}

 

Output:

 

------------------------------------------------------------------------------------

C++ STL class template partial specialization program example

 

24.7.3  Template Function Specialization

#include <iostream>

using namespace std;

 

template <class any_data_type>

any_data_type MyMax(any_data_type Var1, any_data_type Var2)

{

    return Var1 > Var2 ? Var1:Var2;

}

 

// specialization of MyMax() for char *

template<>char* MyMax(char* Var3, char* Var4)

{

    return strcmp(Var3,Var4)> 0 ? Var3:Var4;

}

 

int main()

{

       cout<<"MyMax(10,20) = "<<MyMax(10,20)<<endl;

       cout<<"MyMax('Z','p') = "<<MyMax('Z','p')<<endl;

       cout<<"MyMax(1.234,2.345) = "<<MyMax(1.234,2.345)<<endl;

       char* Var3 = "Function";

       char* Var4 = "Template";

       cout<<"\nTesting...."<<endl;

       cout<<"Address of *Var3 = "<<&Var3<<endl;

       cout<<"Address of *Var4 = "<<&Var4<<endl;

       cout<<"MyMax(\"Function\",\"Template\") = "<<MyMax(Var3,Var4)<<endl;

       return 0;

}

 

Output:

 

C++ STL template function specialization program example

 

24.8  typename Keyword

template <class any_data_type>

class MyClass

{

typename any_data_type::another_data_type * ptr;

//...

};

 

int main()

{

return 0;

}

any_data_type::another_data_type * ptr

MyClass<Test> x;

class Test

{

typedef int another_data_type;

...

};

class Test

{

class another_data_type;

...

};

template <typename any_data_type>

class MyClass

{ };

// *******template.cpp**********

#include <iostream>

#include <string>

// for strcmp()

#include <cstring>

using namespace std;

 

// primary template, for all type

template <class any_data_type>

any_data_type MyMax(const any_data_type Var1, const any_data_type Var2)

{

       cout<<"Primary template..."<<endl;

       return Var1 < Var2 ? Var2 : Var1;

}

 

// specialization for const char *, empty parameter list

template <>

const char *MyMax(const char *Var1, const char *Var2)

{

       cout<<"Specialization..."<<endl;

       // comparison for const char *

       return (strcmp(Var1, Var2)<0) ? Var2 : Var1;

}

 

// do some testing

int main()

{

    // call primary

    int Highest = MyMax(7, 20);

    // call primary

    char p = MyMax('x', 'r');

    string Str1 = "Class", Str2 = "Template";

    // call primary

    string MaxStr = MyMax(Str1, Str2);

    cout<<"The bigger between 7 and 20 is "<<Highest<<endl;