CODE: C CPP Templates and STL

If object-oriented programming teaches C++ how to model behavior,templates teach C++ how to model structure and algorithms — once, for many types, with zero runtime overhead.

Why Do Templates Exist?

Consider this problem:

cpp
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
long add(long a, long b) { return a + b; }

Problems:

  • Code duplication
  • Hard to maintain
  • More types → more overloads
  • Still limited flexibility

What We Want:

  • Write logic once
  • Reuse it for any compatible type
  • Pay zero runtime penalty

The Solution:

Templates


What Is a C++ Template?

A template is a compile-time code generator.

It tells the compiler:

“When you see this template used with a specific type,
generate a real function or class for that type.”

Templates are resolved at compile time — not runtime

  • Template functions
  • Template classes

it is where you find an angle bracket

cpp
template <typename Type> decleration
template <class Type> decleration


Function Templates

Basic Function Template

cpp
template <typename T>
T add(T a, T b) {
    return a + b;
}

Usage:

cpp
add(2, 3);        // T = int
add(2.5, 3.1);    // T = double

What the Compiler Generates

cpp
add<int>(int, int)
add<double>(double, double)

txt
template <typename T>
T add(T, T)

        |
        | Instantiation
        v

int    add(int, int)
double add(double, double)


Multiple Template Parameters

cpp
template <typename T, typename U>
auto multiply(T a, U b) {
    return a * b;
}

Usage:

cpp
multiply(2, 3.5); // T=int, U=double

Generated type:

auto → decltype(a * b) → double


Class Templates

Basic Class Template

cpp
template <typename T>
class Box {
public:
    T value;

    Box(T v) : value(v) {}
};

Usage:

cpp
Box<int> b1(10);
Box<std::string> b2("Hello");

Instantiation diagram:

txt
Box<T>
 |
 |--> Box<int>
 |--> Box<std::string>


Member Function Templates

A class does not need to be templated for its functions to be.

cpp
class Printer {
public:
    template <typename T>
    void print(const T& value) {
        std::cout << value << "\n";
    }
};

Why?

  • One utility class
  • Many data types
  • No duplication

Template Specialization

Full Specialization

Used when one type needs different behavior

cpp
template <typename T>
struct TypeInfo {
    static const char* name() { return "Generic"; }
};

template <>
struct TypeInfo<int> {
    static const char* name() { return "Integer"; }
};

Usage:

cpp
TypeInfo<double>::name(); // Generic
TypeInfo<int>::name();    // Integer


Partial Specialization (Class Templates Only)

cpp
template <typename T>
struct IsPointer {
    static constexpr bool value = false;
};

template <typename T>
struct IsPointer<T*> {
    static constexpr bool value = true;
};

Usage:

cpp
IsPointer<int>::value;    // false
IsPointer<int*>::value;  // true

Pattern matching:

txt
T       -> false
T*      -> true


Variadic Templates (Parameter Packs)

Used when number of arguments is unknown at compile time.

Simple Example

cpp
template <typename... Args>
void printAll(Args... args) {
    (std::cout << ... << args) << "\n";
}

Call:

cpp
printAll(1, " ", 3.14, "\n");

Expansion:

cpp
((cout << 1) << " ") << 3.14 << "\n"


Template Recursion (Old Style)

cpp
template <int N>
struct Factorial {
    static constexpr int value = N * Factorial<N - 1>::value;
};

template <>
struct Factorial<0> {
    static constexpr int value = 1;
};

Compile-time computation:

cpp
int x = Factorial<5>::value; // 120

This runs at compile time


Alias Templates (`using`)

Cleaner alternative to typedef

cpp
template <typename T>
using Vec = std::vector<T>;

Usage:

cpp
Vec<int> v;


Template Constraints (C++20 Concepts)

The Problem

Templates accept anything, even invalid types.

cpp
add("a", "b"); // Compiles? Errors are ugly.

The Solution: Concepts

cpp
#include <concepts>

template <typename T>
requires std::integral<T>
T add(T a, T b) {
    return a + b;
}

Or cleaner:

cpp
template <std::integral T>
T add(T a, T b);


When Should You Use Templates?

Use CaseUse Templates?
Algorithms✅ Yes
Containers✅ Yes
Compile-time config✅ Yes
Runtime polymorphism❌ No
Plugin systems❌ No
Performance-critical code✅ Absolutely

Common Template Pitfalls

1. Code Bloat

Too many instantiations increase binary size.

2. Long Compile Times

Heavy template metaprogramming slows builds.

3. Error Messages

Without concepts → unreadable diagnostics.


Templates in the STL (Real-World Proof)

cpp
std::vector<int>
std::vector<double>
std::sort(begin, end)
std::map<Key, Value>

The entire STL exists because of templates.


Standard Template Library (STL)

C++ added its own library which depends on Templates and called it STL or Standard Template Library.

It is part of the ANSI/ISO C++ standard, meaning every compliant C++ compiler must provide it.

STL is not “just a library”.

It is a design philosophy built on:

  • Generic programming
  • Compile-time polymorphism
  • Performance predictability
  • Separation of data, traversal, and logic

Why STL Exists

Before STL, C++ programmers had to:

  • Reimplement lists, arrays, trees
  • Write custom sorting logic for each data type
  • Manually manage memory and iteration

This led to:

  • Code duplication
  • Bugs
  • Inconsistent performance
  • Non-portable implementations

STL Solves This By Separating Concerns

txt
[ Container ]  ---> stores data
[ Iterator  ]  ---> traverses data
[ Algorithm ]  ---> operates on data

Algorithms don’t care how data is stored.

Containers don’t care what algorithm runs on them.

Templates glue everything together at compile time.


STL Components Overview

The STL consists of three main components:

  • Containers
  • Iterators
  • Algorithms

This separation is one of the most important design decisions in modern C++.