C++ Function and Class Templates
Write reusable type-safe functions and classes, understand instantiation and constraints, and recognize when ordinary overloads are clearer.
Write a function template from an operation contract
Explain instantiation and header visibility
Use constraints or simpler overloads deliberately
The short answer
A template describes code parameterized by a type or value. The compiler instantiates concrete versions for uses that satisfy the required operations; modern constraints make those requirements visible and diagnostics clearer.
Templates parameterize code
An ordinary function fixes its parameter types. A function template replaces part of that type with a parameter such as T. Each call can instantiate a concrete function, preserving static type checking without duplicating the algorithm for int, double, or another suitable type.
Use a template when behavior is genuinely identical across types. If different types require different domain policies, named overloads or separate functions may communicate better.
#include <iostream>
#include <string>
template <typename T>
T larger(const T& first, const T& second)
{
return second < first ? first : second;
}
int main()
{
std::cout << larger(4, 9) << '\n';
std::cout << larger(std::string{"Ada"}, std::string{"Grace"}) << '\n';
}Requirements come from used operations
The larger template requires values that can be compared with < and returned safely through the chosen interface. Without a named constraint, those requirements emerge from the body and failures may produce long diagnostics.
C++20 concepts can name requirements such as total ordering. Even when supporting older compilers, document the expected operations and keep template bodies small enough that errors remain connected to the contract.
| Approach | Strength | Tradeoff |
|---|---|---|
| Ordinary function | Simple diagnostics and fixed contract | One type |
| Overloads | Type-specific behavior | Repeated interface surface |
| Unconstrained template | Broad compatibility | Requirements are implicit |
| Constrained template | Visible requirements | Needs modern language support and design |
Class templates build reusable types
Standard containers are class templates: std::vector<int> and std::vector<std::string> are distinct concrete types generated from one design. Your own class template can model a fixed-size buffer, result wrapper, or generic pair when the type parameter is part of the concept.
Templates are typically defined where callers can see the implementation. Separating them into a source file requires explicit instantiation strategies and is an advanced build decision, not the default beginner layout.
Generic does not mean universal
A useful generic algorithm supports a coherent set of types with clear operations. It does not accept every possible type. Over-generalization can produce unreadable metaprogramming, slow builds, and contracts that appear only in diagnostics.
Start concrete, notice real duplication, then extract the stable common operation. Standard algorithms and containers already solve many generic needs; prefer them before creating another abstraction.
Quick knowledge check
Answer before you reveal.
01Is a template itself a finished function?
It is a pattern; a concrete function is instantiated when used with suitable template arguments.
02Why are many template definitions kept in headers?
The compiler usually needs the complete definition where a concrete instantiation is requested.
Exercise
Practice challenge
Write a clamp_value template that returns a value limited to a lower and upper bound. Test int and double and document the required comparisons.
Requirements
- One implementation serves both tested types
- Values below inside and above the range are tested
- The return type does not silently change
Optional extension: Add a C++20 constraint requiring a totally ordered type.
Open in C++ compilerLesson checkpoint
One small step locks it in
Mark this lesson complete, then keep the momentum going.
Clear up the details
Frequently asked questions
Do templates always make programs faster?
No. They enable compile-time specialization and inlining opportunities but can increase build time and code size; measure relevant paths.
What is type deduction?
The compiler can infer template arguments from function call arguments when the parameter forms make the result unambiguous.
What is a concept?
A C++20 concept names a compile-time constraint on template arguments, documenting requirements and improving overload selection and diagnostics.