C++ Templates, Function & Class Templates, Specialization, Variadic & Concepts Masterclass
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.).
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).
#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;
}
#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;
}
#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!
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 { ... };