* It is annoying to write the same function for every type it needs to operate on. Often the functions on different types are exactly the same, especially when using operator overloading. void swap(int& x, int& y) { int t = x; x = y; y = t; } void swap(double& x, double& y) { double t = x; x = y; y = t; } * C++ has a feature called templates that allows you to abstract a function over its type. template void swap(T& x, T& y) { T temp = x; x = y; y = t; } int main() { int i = 2, j = 3; swap(i, j); double k = 2.0, l = 3.0; swap(k, l); string s = "hello", t = "goodbye"; swap(s, t); } * The compiler behaves exactly as if it had produced 3 different swaps for each of the three types that you used it with. * For the type to work with the function, the function has to have worked as if you had a function of that type with all the T's substituted with that type. i.e. the type has to implement all the operators/member functions that are used on that type. char s[] = "hello", t[] = "goodbye"; swap(s, t); // error, can't use assignment on type char[]. template void stupidsort(T* a, int size) { for(int i = 0; i < size; i++) { int min = i; for(int j = i; j < size; j++) { if(a[j] < a[min]) { min = j; } } swap(a[i], a[min]); } } This will work for any type that allows assignment (for swap) and less-than comparison. i.e. it will work for integers, chars, doubles, strings, any class that overloads the = and < operators. You can declare a function with multiple templates template But you have to make sure you use every template you declare in the function. This isn't done often; in fact, I can't think of a function where you would do this. You can also templatize a class: template class Node { public: Node(T theData, Node* theLink) : data(theData), link(theLink) {} Node* getLink() const { return link; } const T getData() const { return data; } void setData(const T& newData) { data = theData; } void setLink(Node* newLink) { link = newLink; } private: T data; Node *link; }; template class Stack { public: Stack(); virtual ~Stack(); void push(T t); T pop(); bool isEmpty() const; private: Node *top; }; template Stack::Stack() : top(NULL) {} template Stack::~Stack() { T next; while(!isEmpty()) { next = pop(); } } template bool Stack::isEmpty() const { return top == NULL; } template void Stack::push(T t) { Node *n = new Node(t, top); top = n; } template T Stack::pop() { if(isEmpty()) { cout << "Error: popping an empty stack.\n"; exit(1); } T result = top->getData(); Node *discard; discard = top; top = top->getLink(); delete discard; return result; } int main() { Stack intStack; Stack stringStack; intStack.push(3); intStack.push(2); intStack.push(1); stringStack.push("Three"); stringStack.push("Two"); stringStack.push("One"); while(!intStack.isEmpty()) { cout << intStack.pop(); } while(!stringStack.isEmpty()) { cout << stringStack.pop(); } return 0; }