C++ Templates, Function & Class Templates, Specialization, Variadic & Concepts Masterclass

โšก Modern C++ (C++17 / C++20 / C++23) ๐ŸŸข Lesson 13 ๐Ÿ“‚ Phase 13: Templates & Generic Programming ๐Ÿ“… 2026 Master Edition
๐Ÿ“Œ Covered in this in-depth guide: Function Templates ยท Class Templates ยท Non-Type Parameters ยท Template Specialization ยท Variadic Templates ยท Fold Expressions ยท C++20 Concepts ยท Generic Programming

Welcome to Phase 13: Templates & Generic Programming! C++ templates let you write type-independent algorithms and data structures. The compiler generates type-specific specializations at compile time โ€” zero runtime overhead. Templates power the entire STL (vector, map, sort, etc.).

1Function Templates

A function template defines a pattern. The compiler deduces the type argument from the call site, or you can specify it explicitly: maximum<int>(3, 5).

C++ โ€” Function Templatesโ–ถ Run in Compiler
#include <iostream>
#include <string>

// Single type parameter
template <typename T>
T maximum(T first, T second) {
    return first > second ? first : second;
}

// Multiple type parameters
template <typename T, typename U>
auto add(T a, U b) -> decltype(a + b) {
    return a + b;
}

// Non-type template parameter
template <int N>
constexpr int square() { return N * N; }

int main() {
    std::cout << maximum(10, 20) << "
";          // T = int
    std::cout << maximum(4.5, 2.3) << "
";        // T = double
    std::cout << maximum<std::string>("apple", "mango") << "
"; // explicit T
    std::cout << add(3, 4.7) << "
";              // T=int, U=double โ†’ double
    std::cout << square<7>() << "
";              // compile-time: 49
    return 0;
}
2Class Templates
C++ โ€” Class Template (Generic Stack)โ–ถ Run in Compiler
#include <iostream>
#include <vector>
#include <stdexcept>

template <typename T>
class Stack {
    std::vector<T> data_;
public:
    void push(const T& item) { data_.push_back(item); }
    void pop() {
        if (data_.empty()) throw std::underflow_error("Stack underflow!");
        data_.pop_back();
    }
    const T& top() const {
        if (data_.empty()) throw std::underflow_error("Stack is empty!");
        return data_.back();
    }
    bool empty() const { return data_.empty(); }
    std::size_t size() const { return data_.size(); }
};

// Template specialization for bool (memory-efficient bitset version)
template <>
class Stack<bool> {
    std::vector<uint8_t> data_;
public:
    void push(bool val) { data_.push_back(val ? 1 : 0); }
    bool top() const { return data_.back() != 0; }
    void pop() { data_.pop_back(); }
    bool empty() const { return data_.empty(); }
};

int main() {
    Stack<int> intStack;
    intStack.push(10);
    intStack.push(20);
    intStack.push(30);
    std::cout << "Top: " << intStack.top() << "
";
    intStack.pop();
    std::cout << "After pop top: " << intStack.top() << "
";

    Stack<std::string> strStack;
    strStack.push("Hello");
    strStack.push("C++");
    std::cout << "String top: " << strStack.top() << "
";
    return 0;
}
3Variadic Templates & Fold Expressions
C++ โ€” Variadic Templates & Fold Expressionsโ–ถ Run in Compiler
#include <iostream>

// Variadic template: accepts any number of args of any types
template <typename... Args>
void printAll(Args... args) {
    // C++17 fold expression over comma operator
    ((std::cout << args << " "), ...);
    std::cout << "
";
}

// Fold to sum
template <typename... Ts>
auto sumAll(Ts... values) {
    return (values + ...);  // binary fold with +
}

int main() {
    printAll(1, 2.5, "hello", 'A');    // 1 2.5 hello A
    std::cout << sumAll(1, 2, 3, 4, 5) << "
";  // 15
    return 0;
}

C++20 Concepts โ€” Constraining Templates:

Concepts allow placing compile-time constraints on template parameters, improving error messages and enforcing API contracts.

#include <concepts>
template <typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;

template <Numeric T>
T safeDiv(T a, T b) { return a / b; }

// safeDiv("hello", "world"); // โ† COMPILE ERROR โ€” string is not Numeric!
4Technical FAQs

Q1: Why are template definitions in header files?

Templates are compiled per translation unit. The compiler needs the full template definition (not just declaration) at instantiation point โ€” so they must be in headers.

Q2: What is explicit template instantiation?

You can force the compiler to instantiate a template for a specific type: template class Stack<int>; in a .cpp file, reducing compile time.

Q3: What is SFINAE?

Substitution Failure Is Not An Error. When template substitution fails, the compiler silently discards that overload candidate rather than emitting an error. Used with std::enable_if.

Q4: What is the difference between typename and class in template parameters?

They are interchangeable for type parameters. class is historical, typename is preferred in modern C++ for clarity, and is required when disambiguating dependent names.

Q5: What are template template parameters?

A template can accept another template as its parameter: template<template<typename> class Container> class Adapter { ... };