Templates in C++

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;
}

Comments

Popular posts from this blog

Using the Supervisor Controller Pattern to access View controls in MVVM

Getting started with Tesseract optical character recognition (OCR) library in Visual Studio

How to send an e-mail via Google SMTP using C#