Templates in C++

Templates allow writing generic code — code that works with any data type without needing to be rewritten for each type. Instead of writing separate add(int, int), add(float, float), and add(double, double) functions, one template handles all of them.

Why Templates?

Without templates, functions need to be overloaded for each data type — a lot of repetition. Templates solve this by letting the data type become a parameter itself:

// Without template — repetitive
int add(int a, int b)         { return a + b; }
double add(double a, double b){ return a + b; }

// With template — one function for all types
template <typename T>
T add(T a, T b) { return a + b; }

Function Templates

#include <iostream>
using namespace std;

template <typename T>
T getMax(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    cout << getMax(3, 7)       << endl;   // int
    cout << getMax(4.5, 2.1)   << endl;   // double
    cout << getMax('z', 'a')   << endl;   // char
    return 0;
}

Output:

7
4.5
z

Template with Multiple Type Parameters

template <typename T1, typename T2>
void display(T1 a, T2 b) {
    cout << a << " and " << b << endl;
}

int main() {
    display(10, 3.14);
    display("Hello", 100);
    return 0;
}

Output:

10 and 3.14
Hello and 100

Class Templates

Templates can also be applied to entire classes — allowing the class to work with different data types:

#include <iostream>
using namespace std;

template <typename T>
class Stack {
private:
    T data[100];
    int top;

public:
    Stack() : top(-1) {}

    void push(T value) {
        data[++top] = value;
    }

    T pop() {
        return data[top--];
    }

    bool isEmpty() {
        return top == -1;
    }
};

int main() {
    Stack<int> intStack;
    intStack.push(10);
    intStack.push(20);
    cout << intStack.pop() << endl;   // 20
    cout << intStack.pop() << endl;   // 10

    Stack<string> strStack;
    strStack.push("Hello");
    strStack.push("World");
    cout << strStack.pop() << endl;   // World

    return 0;
}

Output:

20
10
World

Template Specialization

Sometimes a template needs special behavior for a specific type. Template specialization provides a custom implementation for that type:

template <typename T>
void print(T x) {
    cout << "Value: " << x << endl;
}

// Specialization for char*
template <>
void print<char*>(char* x) {
    cout << "String: " << x << endl;
}

int main() {
    print(42);
    print(3.14);
    print((char*)"Hello");
    return 0;
}

Output:

Value: 42
Value: 3.14
String: Hello

Default Template Arguments

template <typename T = int>
class Box {
public:
    T value;
    Box(T v) : value(v) {}
    void show() { cout << value << endl; }
};

int main() {
    Box<> b1(100);        // uses default: int
    Box<double> b2(3.14); // explicit type
    b1.show();
    b2.show();
    return 0;
}

Output:

100
3.14

Templates vs Function Overloading

FeatureFunction OverloadingTemplates
Code repetitionSeparate function for each typeOne template for all types
FlexibilityLimited to declared overloadsWorks with any type automatically
Custom behavior per typeEasy — each function is separateRequires specialization

Key Takeaways

  • Templates allow writing generic, type-independent code.
  • Function templates define functions that work with any data type.
  • Class templates define classes that can operate on any data type.
  • Template specialization provides custom behavior for specific types.
  • The STL (Standard Template Library) is entirely built on templates.

Leave a Comment

Your email address will not be published. Required fields are marked *