C++ Templates

Templates are the foundation of generic programming, which is a way of writing code that is independent of any specific type.

A template is a blueprint or formula for creating generic classes or functions. Library containers, such as iterators and algorithms, are examples of generic programming, and they all use the concept of templates.

Each container has a single definition, such asvectorWe can define many different types of vectors, such asvector <int>orvector <string>。

You can use templates to define functions and classes. Let's take a look at how to use them.

function template

The general form of a template function definition is as follows:

template <typename type> ret-type func-name(parameter list) { // function body }

Here, type is a placeholder name for the data type used by the function. This name can be used in the function definition.

The following is an example of a function template that returns the maximum of two numbers:

Example

#include <iostream> #include <string> using namespace std; template <typename T> inline T const& Max (T const& a, T const& b) { return a < b ? b:a; } int main () { int i = 39; int j = 20; cout << "Max(i, j): " << Max(i, j) << endl; double f1 = 13.5; double f2 = 20.7; cout << "Max(f1, f2): " << Max(f1, f2) << endl; string s1 = "Hello"; string s2 = "World"; cout << "Max(s1, s2): " << Max(s1, s2) << endl; return 0; }

When the above code is compiled and executed, it produces the following results:

Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World

class template

Just as we define function templates, we can also define class templates. The general form of a generic class declaration is as follows:

template <class type> class class-name {
.
.
.
}

Here,typeIt is a placeholder type name that can be specified when the class is instantiated. You can use a comma-separated list to define multiple generic data types.

The following example defines the class Stack<> and implements generic methods to push and pop elements:

Example

#include <iostream> #include <vector> #include <cstdlib> #include <string> #include <stdexcept> using namespace std; template <class T> class Stack { private: vector<T> elems; // element public: void push(T const&); // Push void pop(); // Pop T top() const; // returns the top element of the stack bool empty() const{ // returns true if empty. return elems.empty(); } }; template <class T> void Stack<T>::push (T const& elem) { // appends a copy of the passed element elems.push_back(elem); } template <class T> void Stack<T>::pop () { if (elems.empty()) { throw out_of_range("Stack<>::pop(): empty stack"); } // Delete the last element elems.pop_back(); } template <class T> T Stack<T>::top () const { if (elems.empty()) { throw out_of_range("Stack<>::top(): empty stack"); } // returns a copy of the last element return elems.back(); } int main() { try { Stack<int> intStack; // stack of type int Stack<string> stringStack; // stack of type string // operate on the int stack intStack.push(7); cout << intStack.top() <<endl; // operate on the string stack stringStack.push("hello"); cout << stringStack.top() << std::endl; stringStack.pop(); stringStack.pop(); } catch (exception const& ex) { cerr << "Exception: " << ex.what() <<endl; return -1; } }

When the above code is compiled and executed, it produces the following results:

7
hello
Exception: Stack<>::pop(): empty stack
other extensions