Skip to content
Templates Basics
step 1/7

Reading — step 1 of 7

Learn

~2 min readTemplates and STL Algorithms

Templates let you write code that works for any type. The compiler generates a specialized version for each type you use. C++'s killer feature for type-safe generic code.

Function templates

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

int x = max_of(3, 7);              // T deduced as int
double y = max_of(3.5, 2.1);        // T deduced as double
std::string s = max_of<std::string>("hello", "world");   // explicit

The compiler stamps out a max_of<int>, max_of<double>, and max_of<std::string> — one per type you use. Each is type-checked separately.

Class templates

template <typename T>
class Stack {
public:
    void push(T value) { data_.push_back(std::move(value)); }
    T pop() { T t = std::move(data_.back()); data_.pop_back(); return t; }
    bool empty() const { return data_.empty(); }
private:
    std::vector<T> data_;
};

Stack<int> intStack;
Stack<std::string> stringStack;

The whole STL is built on class templates — vector<T>, map<K, V>, unique_ptr<T>, etc.

Multiple type parameters

template <typename K, typename V>
struct Pair {
    K first;
    V second;
};

Pair<std::string, int> p{"Alice", 30};

Non-type template parameters

Templates can take constants, not just types:

template <typename T, size_t N>
class FixedArray {
    T data[N];
public:
    size_t size() const { return N; }
};

FixedArray<int, 10> arr;       // 10 ints, size known at compile time

std::array<T, N> works exactly this way.

Concepts (C++20) — constraining templates

In modern C++, you can require types to satisfy specific concepts:

#include <concepts>

template <std::integral T>
T abs_val(T x) { return x < 0 ? -x : x; }

abs_val(5);        // ✓ int satisfies integral
// abs_val(3.14);  // ✗ compile error — double is not integral

Without concepts, template errors are notoriously cryptic — concepts give clean error messages and document intent.

Most Judge0 setups don't yet support C++20 concepts; older code uses SFINAE or static_assert.

Compile-time vs runtime

Template code is COMPILED, not runtime-dispatched. Compiler generates one version per instantiation:

max_of(3, 7);          // generates max_of<int>
max_of(3.5, 2.1);      // generates max_of<double>

Both versions exist in the compiled binary. Templates trade compile time and binary size for runtime speed — no virtual dispatch, fully inlinable.

Common mistakes

  • Putting template definitions in a .cpp file — usually causes link errors. Templates need their full definition visible to every translation unit that uses them. Define in headers.
  • Mixing types the template wasn't designed for — error messages can be cryptic. Concepts (C++20) help.
  • typename vs class — interchangeable in most contexts: template <typename T> and template <class T> are the same.
  • Excessive instantiation — bloats binary size. Be deliberate about which types you use.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…