Templates, Deeper
cpp2-1 deferred two things: the deeply confusing pre-C++20 template error, and full template depth. This chapter delivers both.
Template Specialization
A different implementation of a template for one specific type.
A real, well-known example: std::vector<bool> has its own famous specialization, bit-packing elements instead of storing full bytes — a genuinely different implementation from every other std::vector<T>.
Partial Specialization
Specializing for a category of types rather than one exact type — a real, useful middle ground.
Variadic Templates
template<typename... Args> accepts an arbitrary number of template arguments.
This is genuinely what powers std::make_unique — used unexplained since cpp2-4 — and similar "forward any number of constructor arguments" functions throughout the STL.
The Confusing Error, Resolved — C++20 Concepts
cpp2-1's own deferred promise: concepts let a template constrain what operations T must support, directly in the template's own declaration.
This moves the error from deep inside the template's own instantiated body to a clear, readable message at the call site itself, naming exactly which requirement wasn't met — a genuine, real quality-of-life improvement.
Contrasted With Rust's Own Trait Bounds
Rust's fn sum<T: Add>(a: T, b: T) -> T has always worked this way, since Rust's very first stable release. Trait bounds constraining a generic parameter aren't a recent addition to Rust the way concepts are to C++ (added in C++20, decades after templates themselves) — another point where Rust simply had, by default and from day one, a discipline C++ has only recently, and optionally, caught up to.
| Concept | C++ Pre-C++20 | C++20 Concepts | Rust Trait Bounds |
|---|---|---|---|
| Constraint expressed where? | nowhere — implicit, discovered on instantiation | in the template declaration itself | in the function signature itself, since day one |
| Error on unmet requirement | deep, confusing, nested inside the instantiation | clear, at the call site, naming the requirement | clear, at the call site, always |
| When introduced | templates since ~1998 | concepts added in C++20 | present from Rust's first stable release |
Coding Challenges
Write a class template Box
Write a variadic template function sum_all(Args... args) that adds together an arbitrary number of arguments using a fold expression, and call it with 2, 3, and 5 arguments, printing each result.
📄 View solutionExplain precisely what C++20 concepts change about WHERE a template's requirements are checked and reported, and why Rust never needed an equivalent feature added later in its own history.
📄 View solutionChapter 2 Quick Reference
- Full specialization — a completely different implementation for one specific type
- Partial specialization — a different implementation for a category of types (e.g. all pointers)
- Variadic templates —
typename... Args, an arbitrary number of arguments; powersmake_uniqueand similar STL functions - C++20 concepts — constraints declared up front, clear errors at the call site instead of deep inside instantiation
- Rust's trait bounds have worked this way since its first stable release — no equivalent retrofit was ever needed
- Next chapter: the Rule of Five and copy/move semantics, in full mechanical depth