C++ Templates



Templates are the foundation of generic programming, a programming style that allows writing functions, classes, algorithms, and different code snippets that work with different data types.

A template is a blueprint or formula for creating a generic class or a function. The library containers like iterators and algorithms are examples of generic programming and have been developed using template concepts.

There is a single definition of each container, such as vector, but we can define many different kinds of vectors, for example, vector <int> or vector <string>.The two keywords that are used to define a template are template and typename.

Function Template

Function templates define a blueprint for functions that enables a function to operate on different data types without rewriting the same logic.

Syntax

The syntax for the general form of a template function definition is shown here −

 template <typename identifier> function_declaration; 

Here the 'template' keyword declares the generic function and 'typename' keyword specifies the type to be used for the parameter.

Example

Here is the following example of a function template that returns the maximum of two values.

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

Output

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

Class Template

Similarly, class templates also define a blueprint for creating classes that can work with any data type.

Syntax

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

Here, type is the placeholder type name, which will be specified when a class is instantiated. You can define more than one generic data type by using a comma-separated list.

Example

Following is the example of defining class Stack<> and implementing generic methods to push and pop the elements from the stack −

 #include <iostream> #include <vector> #include <cstdlib> #include <string> #include <stdexcept> using namespace std; template <class T> class Stack { private: vector<T> elems; // elements public: void push(T const&); // push element void pop(); // pop element T top() const; // return top element bool empty() const { // return true if empty. return elems.empty(); } }; template <class T> void Stack<T>::push (T const& elem) { // append copy of passed element elems.push_back(elem); } template <class T> void Stack<T>::pop () { if (elems.empty()) { throw out_of_range("Stack<>::pop(): empty stack"); } // remove last element elems.pop_back(); } template <class T> T Stack<T>::top () const { if (elems.empty()) { throw out_of_range("Stack<>::top(): empty stack"); } // return copy of last element return elems.back(); } int main() { try { Stack<int> intStack; // stack of ints Stack<string> stringStack; // stack of strings // manipulate int stack intStack.push(7); cout << intStack.top() <<endl; // manipulate 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; } } 

Output

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

Template Argument Deduction

Template argument deduction is a feature that automatically deduces (understands) the data type of the argument passed to a function or class template. Instead of explicitly specifying template arguments, the compiler figures them out for you.

Example

Lets see an example of the Template Argument Deduction −

 template<typename T> T add(T a, T b) { return a + b; } int main() { // The compiler deduces T as int auto result1 = add(5, 3); // The compiler deduces T as double auto result2 = add(3.14, 2.86); } 

In this code, we didn't write add<int>(5,3) or add<double>(3.14, 2.86). The compiler deduces the type based on the arguments you provide.

Function Template Argument Deduction

In C++ Function template argument is a feature that allows the compiler to automatically deduce the types of template parameters based on the arguments passed to the function.

Example

Heres a simple example of a Function template argument deduction.

 #include <iostream> // Function template template<typename T> void printValue(T value) { std::cout << value << std::endl; } int main() { // Usage examples printValue(42); // T is int printValue("Hello"); // T is const char* printValue(3.14159); // T is double return 0; } 

Output

 42 Hello 3.14159 

Class Template Argument Deduction

Class template argument deduction in C++ is a feature that enables the compiler to automatically infer template parameters for class templates from the constructor arguments when creating an object.

Example

Heres a basic implementation of class template deduction.

 #include <iostream> template<typename T> class Holder { public: Holder(T value) : data(value) {} void show() const { std::cout << data << std::endl; } private: T data; }; int main() { Holder h1(42); // T deduced as int Holder h2(3.14); // T deduced as double Holder h3("Hello"); // T deduced as const char* h1.show(); // Output: 42 h2.show(); // Output: 3.14 h3.show(); // Output: Hello return 0; } 

Output

 42 3.14 Hello 

Benefits of C++ Templates

  • Code Reusability − Templates enable you to write generic code that works with all data types, thus eliminating the need to write identical code for each required type. This saves development time by reducing code duplication.
  • Reduced Maintenance − Update a template and see the changes across all instantiations. Which applies better in terms of bug fixing, fixing ones, and seeing the benefits of all the instantiations.
  • Enhanced Performance − Template instantiations occur at compile time, reducing run time errors. The compiler optimizes the code for specific data types.
  • Organize the code better − Since templates separate the algorithmic logic from the data type it helps in creating modular code which further is good in terms of development scenario. It helps reduce searching for different implementations of a code.
Advertisements
close