Templates and Concepts¶
Templates define families of types or functions. Instantiation substitutes template arguments and checks the resulting program. Concepts name constraints and improve both interfaces and diagnostics.
Function template¶
This requires a usable < expression and compatible return behavior, but the
unconstrained signature does not communicate that requirement.
Constrained template¶
#include <concepts>
template<std::totally_ordered T>
T maximum(T left, T right) {
return left < right ? right : left;
}
A concept is a compile-time predicate over template arguments. It specifies syntactic and, by documented semantic requirements, behavioral expectations. The compiler can check expressions but cannot generally prove laws such as transitivity.
Custom concept¶
template<typename R>
concept SizedRange = requires(R const& range) {
{ range.size() } -> std::convertible_to<std::size_t>;
range.begin();
range.end();
};
Keep constraints at the abstraction level the algorithm actually needs. Requiring a concrete container where only a range is necessary reduces reuse.
Instantiation and visibility¶
Template definitions normally need to be visible where implicit instantiation occurs, which is why they commonly live in headers. Explicit instantiation can move selected generation to source files. Each specialization must still obey the One Definition Rule.
Class templates and deduction¶
template<typename T>
class box {
public:
explicit box(T value) : value_{std::move(value)} {}
T const& get() const noexcept { return value_; }
private:
T value_;
};
box value{std::string{"notes"}}; // class template argument deduction
Static polymorphism and type erasure¶
Templates provide compile-time polymorphism and can inline concrete operations.
Type erasure, as used by facilities such as std::function, provides a uniform
runtime value interface without exposing the concrete type. Virtual interfaces,
variants, templates, and type erasure have different extensibility, allocation,
ABI, compile-time, and diagnostic trade-offs.
Exercises¶
- Constrain a mean function to a numeric input range and valid result type.
- Explain which semantic properties a compiler cannot infer from a concept.
- Compare a virtual strategy with a templated strategy.