Templates
The Cookie Cutter
Imagine a star-shaped cookie cutter. It doesn't care if you use chocolate dough, sugar dough, or gingerbread β same shape, different material. That's a template in C++.
Instead of writing a separate maxInt(), maxDouble(), maxString(), you write one template function and let the compiler stamp out the right version for each type you actually use. Zero runtime cost β it's all resolved at compile time.
Function Templates
A function template is a blueprint. You write it with a placeholder type, and the compiler generates concrete functions as needed.
Template max Function
Template Type Deduction
Usually you don't need to spell out the type β the compiler deduces it from the arguments:
myMax(3, 7)β compiler sees twoints, stamps outmyMax<int>myMax(3.14, 2.72)β twodoubles, stamps outmyMax<double>
But when types conflict (myMax(3, 2.5) β int and double), you need to specify explicitly: myMax<double>(3, 2.5).
Class Templates
Templates aren't just for functions β you can template entire classes. This is how vector<int>, map<string, int>, and every other STL container works.
Template Stack Class
Template Specialization
Sometimes the generic version doesn't work well for a specific type. You can specialize β provide a custom implementation for that type while keeping the generic version for everything else.
Specialization for string
auto with Templates (C++14+)
Variadic Templates (Brief)
C++11 introduced variadic templates β templates that accept any number of arguments. This is how std::tuple, std::make_unique, and printf-like functions work.
template <typename... Args>
void print(Args... args) {
((cout << args << " "), ...);
cout << endl;
}
print(1, "hello", 3.14); // 1 hello 3.14The ... is a parameter pack. The fold expression ((cout << args << " "), ...) expands it for each argument.
C++20 Concepts (Brief)
Concepts let you constrain template parameters so that you get clear error messages instead of pages of cryptic template errors:
template <typename T>
requires std::integral<T>
T gcd(T a, T b) { return b == 0 ? a : gcd(b, a % b); }
gcd(12, 8); // OK: int is integral
// gcd(1.5, 2.0); // ERROR: clear message about double not being integralConcepts are one of the biggest quality-of-life improvements in modern C++.
SFINAE (Mention)
Before concepts, C++ used SFINAE (Substitution Failure Is Not An Error) β a rule where if a template instantiation fails, the compiler silently tries other overloads instead of erroring. It works, but the syntax is ugly. If you're writing C++20 or later, prefer concepts.