Templates let you write generic code that works with any type. A function template such as template<typename T> T max(T a, T b) { return (a > b) ? a : b; } defines a family of functions, and the compiler generates a concrete version for each type used, a process called template instantiation. A class template follows the same idea for types: template<typename T> class Stack { std::vector<T> data; public: void push(T val); T pop(); } is used as Stack<int> s. Template specialization provides a custom implementation for a particular type, with full specialization covering one specific type and partial specialization covering a subset of the template parameters. Non-type template parameters accept values rather than types, as in template<int N> struct Buffer { char data[N]; }, and from C++20 they may also be literal class types.
Variadic templates accept any number of template arguments using parameter packs, as in template<typename... Args> void f(Args... args). The packs are expanded using recursion in older code or, since C++17, more concisely with fold expressions, which reduce a parameter pack over a binary operator such as +, *, &&, ||, or the comma operator. Template metaprogramming uses templates to perform computation at compile time, producing highly optimized code but with a notoriously steep learning curve; std::tuple, std::integral_constant, and many type traits are implemented this way.
Compile-time constraint of templates relies on SFINAE, the principle that Substitution Failure Is Not An Error: when substituting template parameters fails for an overload, that overload is silently removed rather than aborting compilation. std::enable_if<Cond, T> yields T only when Cond is true, and std::void_t detects whether an expression is well-formed, together enabling compile-time checks for type properties. C++20 concepts replace most SFINAE boilerplate with named compile-time predicates written in the natural syntax template<std::integral T> T add(T a, T b) { return a + b; }, producing clearer error messages and more readable constraints. The three-way comparison operator, known as the spaceship operator, returns a comparison category type, and using = default on it makes the compiler generate all six relational operators automatically. constexpr marks a variable or function as evaluable at compile time whenever given constant expressions, with consteval in C++20 requiring compile-time evaluation; constexpr implies const, but const alone does not imply compile-time evaluation. The inline keyword serves a different role: it allows a function to be defined identically in multiple translation units without violating the One Definition Rule, and modern compilers also use it as a hint to expand the body at call sites.