Zzz
Zzz

Reputation: 3025

Template Function: How to make a template function with a template class as an argument?

Is it possible to make a template for a function that has a template class in its argument list?

I would like to make one template for statSelection() and statInsertion() that would allow me to test different sorting algorithms without having to create a separate stat function for each type of sorting algorithm I am testing. (My sorting algorithms are template classes)

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include "FileGen.h"
#include "FileRead.h"
#include "SelectionSort.h"
#include "SelectionSort.cpp"
#include "InsertionSort.h"
#include "InsertionSort.cpp"

using namespace std;

void statSelection(int[], int[], Selection<int>, Selection<int>);
void statInsertion(int[], int[], Insertion<int>, Insertion<int>);

int main () 
{
    FileGen fileGen;
    FileRead fileRead;
    Selection<int> selectHundred;
    Selection<int> selectThousand;
    Insertion<int> insertionHundred;
    Insertion<int> insertionThousand;
    int valuesHundred[100];
    int valuesThousand[1000];
    fileGen.generateFiles();
    fileRead.readFiles(valuesHundred, valuesThousand);
    statSelection(valuesHundred, valuesThousand, selectHundred, selectThousand);
    fileGen.generateFiles();
    fileRead.readFiles(valuesHundred, valuesThousand);
    statInsertion(valuesHundred, valuesThousand, insertionHundred, insertionThousand);
    system("pause");
    return 0;
}

void statSelection(int vHundred[], int vThousand[], Selection<int> sHundred, Selection<int> sThousand)
{
    cout << "One Hundred Items" << endl;
    sHundred.SelectionSort(vHundred, 100);
    sHundred.selectionSortPreformance();
    cout << "One Thousand Items" << endl;
    sThousand.SelectionSort(vThousand, 1000);
    sThousand.selectionSortPreformance();
}

void statInsertion(int vHundred[], int vThousand[], Insertion<int> iHundred, Insertion<int> iThousand)
{
    cout << "One Hundred Items" << endl;
    iHundred.InsertionSort(vHundred, 100);
    iHundred.insertionSortPreformance();
    cout << "One Thousand Items" << endl;
    iThousand.InsertionSort(vThousand, 1000);
    iThousand.insertionSortPreformance();
}

Upvotes: 1

Views: 167

Answers (4)

phschoen
phschoen

Reputation: 2081

you can use a class like this:

template <class T>
class Sortclass
{
public:
    virtual void sort(T array[] , int size) = 0;
    virtual void preformance() = 0;
};

template <class T>
class AsortClass : public Sortclass<T> 
{
public:
    virtual sort(T array[] , int size)
    {
        //do stuff
    }

    virtual void preformance()
    {
        //do stuff
    }
};

template <class T>
void stat(T vHundred[], T vThousand[], Sortclass<T>& iHundred, Sortclass<T>& iThousand)
{
    cout << "One Hundred Items" << endl;
    iHundred.sort(vHundred, 100);
    iHundred.preformance();
    cout << "One Thousand Items" << endl;
    iThousand.sort(vThousand, 1000);
    iThousand.preformance();
}    

then you can inherit from this class and implement the sort funktion. with this you can change the sort algorythm realy easy without changing the stat function.

its called strategy pattern see: http://en.wikipedia.org/wiki/Strategy_pattern

Upvotes: 0

Barney Szabolcs
Barney Szabolcs

Reputation: 12514

I would rather use polymorphism. (The solution without polymorphism can be found after a horizontal rule)

I would inherit both Insertion<_Tp> and Selection<_Tp> from an abstract class (interface) called ISortable<_Tp>, and name .InsertionSort and .SelectionSort member functions simply as .Sort (which would be a virtual member function of Sortable<_Tp>).

template<typename _Tp>
class ISortable<_Tp>{
public:
    virtual void Sort(_Tp *, int)=0; // btw functions are usually lowercase
    virtual void Performance()=0; 
};

template<typename _Tp>
class InsertionSort<_Tp> : public Sortable<_Tp>{
//...
    virtual void Sort(_Tp *, int); 
    virtual void Performance(); 
};
//...

So your function can be written like this:

void statSelection(int[], int[], Sortable<int>&, Sortable<int>&);

void statSelection(int[], int[], Sortable<int>&sHundred, Sortable<int>&)
{
//...
  sHundred.Sort(vHundred, 100);
  sHundred.Performance();
//...
}

Solution without polymorphism:

It is possible to do, just name BOTH your sort and performance functions with the same name.

Then

template<typename _Tp_sortable>
void statGeneral(int[], int[], _Tp_sortable sHundred, _Tp_sortable)
{
//...
  sHundred.Sort(vHundred, 100);
  sHundred.Performance();
//...
}

The examples: (Im not sure if you actually need the <Selection<int> > part after the function, but I'd call it with it.)

statGeneral<Selection<int> >(valuesHundred, valuesThousand, selectHundred, selectThousand);
statGeneral<Insertion<int> >(valuesHundred, valuesThousand, insertionHundred, insertionThousand);

Upvotes: 2

juanchopanza
juanchopanza

Reputation: 227370

It isn't clear what you are after, but this is a function template that has a class template parameter.

// class template
template <typename T> class Foo {};

// function template
template <typename T>
T doSomething(const Foo<T>& f) { .... }

If you want to be able to specify the class template as a template parameter, then you need a "template template parameter":

// class templates
template <typename T> class Foo {};
template <typename T> class Bar {};

template <template<class> class T1, class T2>
T2 doSomething(const T1<T2>& f);

Foo<int> f;
Bar<double> b;
int n = doSomething(f);
double x = doSomething(b);

Upvotes: 1

Nikos C.
Nikos C.

Reputation: 51832

Something like this perhaps?

template <typename T>
void statSelection(T vHundred[], T vThousand[], Selection<T> sHundred, Selection<T> sThousand);

template <typename T>
void statInsertion(T vHundred[], T vThousand[], Insertion<T> iHundred, Insertion<T> iThousand);

Upvotes: 1

Related Questions