An introduction to using template classes in C++, that starts extremely simply and builds up from there…
Example 1
Consider the following simple class that we use to store and print an integer:
#include <iostream>
class A
{
private:
int data;
public:
A( const int& d );
int Value() const;
void Print() const;
};
A::A( const int& d )
{
data = d;
}
int A::Value() const
{an
return data;
}
void A::Print() const
{
std::cout << data << std::endl;
}
int main()
{
A a( 5 );
a.Print();
}
Now suppose we wish to do this in a generic way, allowing us to store and print not only integers, but any kind of primitive data type. The equivalent template class for class A would now look like this:
#include <iostream>
template< class T>
class A
{
private:
T data;
public:
A( const T& d );
T& Value() const;
void Print() const;
};
template<class T>
A<T>::A( const T& d )
{
data = d;
}
template<class T>
T& A<T>::Value() const
{
return data;
}
template<class T>
void A<T>::Print() const
{
std::cout << data << std::endl;
}
int main()
{
A<int> a( 5 );
a.Print();
return 0;
}
Example 2
In this example class A is used to maintain a std::vector of generic data types, with functions to add to the vector set and print their contents:
#include <iostream> #include <vector>#include#include template class Queue { private: std::vector data; public: void push(T const &); void pop(); T front() const; void Print(); }; template void Queue ::push(T const &d) { data.push_back(d); } template void Queue ::pop() { data.erase(data.begin( ) + 0,data.begin( ) + 1); } template T Queue ::front() const { if ( data.size() > 0 ) { return *(data.begin()); } else { std::cerr << "Empty Queue. Returning garbage value\n"; T* temp = new(T); T garbage = * temp; delete temp; return garbage; } } template void Queue ::Print() { for ( int i = 0; i < (int) data.size(); i++ ) { T val = *( data.begin() + i ); std::cout << val << std::endl; } } int main() { Queue q; q.push(1); q.push(2); std::cout << q.front() << std::endl; std::cout << "Before removing data" << std::endl; q.Print(); q.pop(); std::cout << "After removing data"<< std::endl; q.Print(); return 0; } #include <string> template< class T> class A { private: std::vector<T> v; public: void Add( const T& d ); T& Value(const int& index) const; void Print() const; }; template<class T> void A<T>::Add( const T& d ) { v.push_back(d); } template<class T> T& A<T>::Value(const int& index) const { T val = 0; if (index < v.size() ) { val = v[ index ]; } return val; } template<class T> void A<T>::Print() const { for ( int i = 0; i < (int) v.size(); i++ ) { T val = *( v.begin() + i ); std::cout << val << std::endl; } } int main() { A<int>* a1 = new A<int>(); a1->Add( 4 ); a1->Add( 5 ); a1->Print(); delete a1; A<std::string> a2; a2.Add( "Hello" ); a2.Add( "World" ); a2.Print(); return 0; }
Example 3
This example uses a template function for finding the maximum of two generic data types:
#include <ostream>
#include <vector>
#include <string>
const int& Max( const int& a, const int& b )
{
return a > b ? a : b;
}
template<class T>
inline const T& Max1( const T& a, const T& b )
{
return a > b ? a : b;
}
int main()
{
int max = Max( 5, 55 );
std::cout << max << std::endl;
double maxd = Max1( 23.3, 101.23 );
std::cout << maxd << std::endl;
float maxf = Max1( 23.2, 111.1 );
std::cout << maxf << std::endl;
return 0;
}
Example 4
An example of using template classes in a queue, to store generic data types:
#include <iostream>
#include <vector>
template <class T>
class Queue
{
private:
std::vector<T> data;
public:
void push(T const &);
void pop();
T front() const;
void Print();
};
template <typename T>
void Queue<T> ::push(T const &d)
{
data.push_back(d);
}
template <typename T>
void Queue<T>::pop()
{
data.erase(data.begin( ) + 0,data.begin( ) + 1);
}
template <typename T>
T Queue<T>::front() const
{
if ( data.size() > 0 )
{
return *(data.begin());
}
else
{
std::cerr << "Empty Queue. Returning garbage value\n";
T* temp = new(T);
T garbage = * temp;
delete temp;
return garbage;
}
}
template <typename T>
void Queue<T>::Print()
{
for ( int i = 0; i < (int) data.size(); i++ )
{
T val = *( data.begin() + i );
std::cout << val << std::endl;
}
}
int main()
{
Queue<int> q;
q.push(1);
q.push(2);
std::cout << q.front() << std::endl;
std::cout << "Before removing data" << std::endl;
q.Print();
q.pop();
std::cout << "After removing data"<< std::endl;
q.Print();
return 0;
}