Lesson 54 of 60 – Templates in C++
90%

Templates in C++

Templates are a powerful feature of C++ that allow you to write generic and reusable code. A template lets you define a function or class without specifying the exact data type in advance.

Note: Templates are mainly used for generic programming. They allow the same code to work with different data types while maintaining compile-time type checking.

1. What is a Template?

A template is a blueprint for creating functions or classes that can work with different data types.

template <typename T>
T add(T a, T b) {

    return a + b;
}

Here, T represents a type that will be provided when the function is used.

2. Why Use Templates?

Templates help reduce duplicate code.

Without templates, you may need separate functions for different data types.

int add(int a, int b);

double add(double a, double b);

A template can handle both types using one generic function.

template <typename T>
T add(T a, T b) {

    return a + b;
}

3. Function Templates

A function template defines a generic function that can work with different data types.

template <typename T>
T maximum(T a, T b) {

    return (a > b) ? a : b;
}

The same function can be used with integers, floating-point values, and other compatible types.

4. Basic Function Template Example

#include <iostream>

template <typename T>
T add(T a, T b) {

    return a + b;
}

int main() {

    std::cout <<
        add(10, 20)
        << std::endl;

    std::cout <<
        add(2.5, 3.5);

    return 0;
}

The compiler can generate suitable versions of the function for the types used in the calls.

5. typename Keyword

The typename keyword is commonly used to declare a type parameter in a template.

template <typename T>
void display(T value) {

    std::cout << value;
}

Here, T is a placeholder for a data type.

6. Using class Instead of typename

The keyword class can also be used for a type parameter in a template declaration.

template <class T>
T square(T value) {

    return value * value;
}

For a type parameter, typename and class are generally interchangeable in this context.

7. Template with Different Data Types

template <typename T>
void display(T value) {

    std::cout <<
        value
        << std::endl;
}

int main() {

    display(10);

    display(5.5);

    display('A');

    display("Hello");

    return 0;
}

The template can work with different types as long as the operations used by the template are valid for those types.

8. Template with Two Type Parameters

A template can use more than one type parameter.

template <typename T, typename U>
void display(T first, U second) {

    std::cout <<
        first << " "
        << second;
}

Here, T and U can represent different types.

9. Example with Two Types

#include <iostream>

template <typename T, typename U>
void display(
    T first,
    U second
) {

    std::cout <<
        first << " "
        << second;
}

int main() {

    display(
        10,
        5.5
    );

    return 0;
}

The first parameter can be an integer while the second parameter can be a floating-point value.

10. Template Type Deduction

When a function template is called, the compiler can often determine the template type from the function arguments.

template <typename T>
T square(T value) {

    return value * value;
}

int result = square(5);

double value = square(2.5);

The compiler deduces T from the argument.

11. Explicit Template Arguments

You can explicitly specify a template type when needed.

template <typename T>
T add(T a, T b) {

    return a + b;
}

double result =
    add<double>(
        10,
        20
    );

Here, double is explicitly specified as the template type.

12. Multiple Template Parameters

template <typename T, typename U, typename V>
void show(
    T a,
    U b,
    V c
) {

    std::cout <<
        a << " "
        << b << " "
        << c;
}

A template can have multiple type parameters when a generic operation requires them.

13. Class Templates

Templates can also be used with classes.

template <typename T>
class Box {

private:

    T value;

public:

    Box(T v) {

        value = v;
    }

    T getValue() {

        return value;
    }
};

The class can store different types depending on the template argument.

14. Creating Objects of a Class Template

Box<int> intBox(100);

Box<double> doubleBox(25.5);

std::cout <<
    intBox.getValue()
    << std::endl;

std::cout <<
    doubleBox.getValue();

The template argument specifies the type used by the class.

15. Complete Class Template Example

#include <iostream>

template <typename T>
class Calculator {

public:

    T add(
        T a,
        T b
    ) {

        return a + b;
    }

    T multiply(
        T a,
        T b
    ) {

        return a * b;
    }
};

int main() {

    Calculator<int> calc;

    std::cout <<
        calc.add(10, 20)
        << std::endl;

    std::cout <<
        calc.multiply(5, 4);

    return 0;
}

16. Class Template with Multiple Types

template <typename T, typename U>
class Pair {

private:

    T first;

    U second;

public:

    Pair(T a, U b)
        : first(a),
          second(b) {
    }

    void display() {

        std::cout <<
            first << " "
            << second;
    }
};

Different types can be stored in the same class template.

17. Default Template Arguments

A class template can provide a default type for a template parameter.

template <
    typename T = int
>
class Number {

private:

    T value;

public:

    Number(T v)
        : value(v) {
    }

    T getValue() {

        return value;
    }
};

If no type is specified, int is used.

18. Template Specialization

Template specialization allows a programmer to provide a specialized implementation for a particular type.

template <typename T>
class Printer {

public:

    void print(T value) {

        std::cout <<
            value;
    }
};

template <>
class Printer<bool> {

public:

    void print(bool value) {

        std::cout <<
            (value ? "true" : "false");
    }
};

The second class provides a special implementation for bool.

19. Function Template Specialization

template <typename T>
void display(T value) {

    std::cout <<
        value;
}

template <>
void display<bool>(bool value) {

    std::cout <<
        (value ? "TRUE" : "FALSE");
}

A function template can also have a specialized implementation for a specific type.

20. Non-Type Template Parameters

Templates can also have non-type parameters such as integer values.

template <
    typename T,
    int SIZE
>
class Array {

private:

    T data[SIZE];

public:

    int size() {

        return SIZE;
    }
};

Here, SIZE is a compile-time value rather than a type.

21. Template with an Array Size

template <typename T, int SIZE>
class Array {

private:

    T data[SIZE];

public:

    void set(
        int index,
        T value
    ) {

        if(index >= 0 &&
           index < SIZE) {

            data[index] = value;
        }
    }

    T get(int index) {

        return data[index];
    }

    int size() {

        return SIZE;
    }
};

int main() {

    Array<int, 5> numbers;

    numbers.set(0, 100);

    std::cout <<
        numbers.get(0);

    return 0;
}

22. Templates and Code Reusability

Templates allow one generic implementation to work with many compatible types.

template <typename T>
T maximum(
    T a,
    T b
) {

    return a > b ? a : b;
}

int a = maximum(10, 20);

double b =
    maximum(10.5, 5.5);

This reduces the need to write duplicate functions.

23. Templates and Type Safety

Templates provide compile-time type checking.

template <typename T>
T multiply(T a, T b) {

    return a * b;
}

int result =
    multiply(5, 10);

The compiler checks whether the requested operation is valid for the selected type.

24. Templates and Standard Library

The C++ Standard Library uses templates extensively.

Examples include:

  • std::vector<T>
  • std::list<T>
  • std::map<K, V>
  • std::set<T>
  • std::pair<T, U>
#include <vector>

std::vector<int> numbers;

std::vector<double> prices;

The same container template can work with different element types.

25. Templates and Generic Algorithms

Many standard algorithms are implemented as templates so that they can work with different container and element types.

#include <algorithm>
#include <vector>

std::vector<int> numbers = {
    40, 10, 30, 20
};

std::sort(
    numbers.begin(),
    numbers.end()
);

The generic algorithm can operate on many compatible types.

26. Common Mistakes with Templates

  • Forgetting the template declaration.
  • Using an operation that is not supported by the selected type.
  • Confusing template parameters with normal function parameters.
  • Using too many unnecessary template parameters.
  • Creating overly complicated template code.
  • Forgetting to specify a required template argument.
  • Assuming every type can be used with every template operation.

27. Advantages of Templates

  • Code Reuse: The same generic code can work with different types.
  • Type Safety: Many errors can be detected at compile time.
  • Less Duplication: Separate implementations for every type are often unnecessary.
  • Flexibility: Templates can work with user-defined and standard types.
  • Performance: Template code is generally generated at compile time, avoiding the need for runtime type-based dispatch in many cases.
  • Generic Programming: Templates are a foundation of generic programming in C++.

28. Best Practices for Templates

  • Keep templates simple and focused.
  • Use meaningful template parameter names when clarity matters.
  • Document the operations and requirements expected from template types.
  • Use templates when generic behavior provides real value.
  • Avoid unnecessary template complexity.
  • Prefer standard library templates when they already solve the problem.
  • Test templates with different valid types.
  • Use concepts in modern C++ when appropriate to express type requirements clearly.

29. Practical Generic Calculator

#include <iostream>

template <typename T>
class Calculator {

public:

    T add(
        T a,
        T b
    ) {

        return a + b;
    }

    T subtract(
        T a,
        T b
    ) {

        return a - b;
    }

    T multiply(
        T a,
        T b
    ) {

        return a * b;
    }
};

int main() {

    Calculator<int> intCalc;

    Calculator<double> doubleCalc;

    std::cout <<
        intCalc.add(10, 20)
        << std::endl;

    std::cout <<
        doubleCalc.multiply(
            2.5,
            4.0
        );

    return 0;
}

The same calculator class can work with different numeric types.

30. Templates – Final Summary

Concept Meaning
Template A blueprint for writing generic functions or classes.
Function Template A generic function that can work with different types.
Class Template A generic class that can work with different types.
typename Common keyword used to declare a type template parameter.
Template Parameter A placeholder for a type or compile-time value.
Specialization A customized implementation for a particular template argument.
Non-Type Parameter A compile-time value used as a template parameter.
template <typename T>
T maximum(
    T a,
    T b
) {

    return a > b ? a : b;
}

int main() {

    std::cout <<
        maximum(10, 20)
        << std::endl;

    std::cout <<
        maximum(5.5, 2.5);

    return 0;
}

Templates allow C++ programmers to create reusable, type-safe, generic code that can work with many compatible data types.

📌 Key Points

  • Templates are used for generic programming in C++.
  • A function template can work with different data types.
  • A class template can create classes for different types.
  • typename is commonly used for type parameters.
  • Templates reduce duplicate code.
  • Template type arguments can often be deduced automatically.
  • Templates can have multiple type parameters.
  • Template specialization provides customized behavior for specific types.
  • Non-type template parameters can represent compile-time values.
  • The C++ Standard Library uses templates extensively.

🧠 Quick Quiz

Question: What is the main purpose of templates in C++?