Function and class templates
Write reusable generic functions and classes using template parameters and understand basic instantiation.
Learning objectives
- Explain why templates support generic programming.
- Write a function template.
- Write a simple class template.
- Understand template argument deduction at a beginner level.
Prerequisites: functions, classes, overloads, and basic type deduction with auto. Examples use standard template syntax available since C++98; later features are labelled separately.
Why templates?
A function that finds the larger of two integers and a function that finds the larger of two doubles may repeat the same logic. A template lets you describe the logic once while allowing the compiler to generate a suitable specialization for the types used.
Function template
template <typename T>
T maximum(T left, T right) {
return (left < right) ? right : left;
}
int main() {
int a = maximum(3, 8);
double b = maximum(2.5, 1.5);
}typename T introduces a template type parameter. When you call maximum(3, 8), the compiler deduces T as int. For the second call, it deduces double. The type must support the operations used inside the template; in this case, the less-than comparison and returning a value of type T.
Class template
template <typename T>
class Box {
public:
explicit Box(T value) : value(value) {}
const T& get() const { return value; }
private:
T value;
};
Box<int> number{42};
Box<std::string> label{"C++"};The class template defines a family of types. Box<int> and Box<std::string> are different specializations.
Templates and errors
Template code is checked when it is instantiated for a particular set of template arguments. A type that does not support the operations required by the template will produce a diagnostic when that specialization is needed. Good templates make their requirements clear and avoid assuming more than they use.
Common mistakes
- Forgetting the
templatedeclaration before the function or class. - Using an operation that the chosen type does not support.
- Assuming different argument types will always deduce one common T.
- Writing overly generic templates when a normal function would be clearer.
Practice
- Write a template that returns the smaller of two values.
- Create a Pair class template with two type parameters.
- Try calling maximum with an int and a double; inspect the deduction diagnostic, then make the types explicit or redesign the template.
- Explain why a template is a compile-time pattern rather than one ordinary runtime function that changes its type.
Practice solutions
Show worked solutions
template <typename T> T smaller(T left, T right) { return (right < left) ? right : left; }Both arguments must deduce the sameT, andTmust support comparison and copying.template <typename First, typename Second> struct Pair { First first; Second second; };Each template argument determines the type of one member.- A call such as
maximum(3, 4.5)can fail deduction because the two arguments suggest different types for the same template parameter. Usemaximum<double>(3, 4.5)or convert both arguments to a common type. - A template describes how the compiler can generate a specialization for particular template arguments. The compiler performs that instantiation during translation; the resulting program executes ordinary compiled functions.
Check your understanding
When does the compiler determine a template specialization?
Answer: When the template is instantiated for particular template arguments, commonly because code uses that specialization.
Summary
Templates let you write type-independent algorithms and data structures. Start with simple type parameters, understand the operations the template requires, and keep generic code as simple as the problem allows.