C++ Tutorial
C++ Templates
A function template writes one algorithm for many types. The compiler fills in int, double, or string.
One recipe, many types
You already saw function overloading: two functions named add, one for int and one for double. The bodies were the same idea copied twice. A template is that idea written once. You name a placeholder type, usually T. At each call, the compiler substitutes the real type and compiles a concrete function.
That substitution happens at compile time. There is no extra decision while the program runs. If the body does not make sense for a type — say you compare two values and that type has no > — g++ reports an error at the call site.
Function template bigger
bigger returns whichever argument compares greater. Prefix the function withtemplate <typename T>. Use T as the parameter type and the return type. The same source covers int and double.
Example
#include <iostream>
using namespace std;
template <typename T>
T bigger(T a, T b) {
if (a > b) {
return a;
}
return b;
}
int main() {
cout << bigger(3, 9) << endl;
cout << bigger(2.5, 2.25) << endl;
return 0;
}Output is 9 then 2.5. The first call builds bigger<int>. The second builds bigger<double>. You did not write those names; the compiler did.
Run this in /cpp/try with Try it in C++. Swap the numbers. Do not paste it into the Python editor at /try.
The compiler fills in T
Both arguments must agree on T in this version. bigger(3, 9) is fine.bigger(3, 9.1) is not: one argument is int, the other is double, and the template asked for a single T. Cast one side, or write a template that takes two type parameters. This page keeps one T.
You can name the type at the call if you want it written down: bigger<int>(3, 9). Most code lets the compiler infer it from the arguments.
| Call | T becomes |
|---|---|
bigger(3, 9) | int |
bigger(2.5, 2.25) | double |
bigger(word, other) | string |
Strings work the same way
string already defines > (lexicographic order). Include<string> and pass two strings. The template body does not change.
Example
#include <iostream>
#include <string>
using namespace std;
template <typename T>
T bigger(T a, T b) {
if (a > b) {
return a;
}
return b;
}
int main() {
string left = "kappa";
string right = "omega";
cout << bigger(left, right) << endl;
return 0;
}Output is omega, because 'o' sorts after 'k'. The algorithm was “return the greater of two values.” The type supplied the comparison.
A tiny class template: Box
A class template is the same placeholder idea on a type. Box<T> holds one value of whatever T you name. Box<int> and Box<string> are two different types. You cannot assign one to the other without converting the contents yourself.
Example
#include <iostream>
#include <string>
using namespace std;
template <typename T>
struct Box {
T value;
};
int main() {
Box<int> count;
count.value = 4;
Box<string> title;
title.value = "draft";
cout << count.value << endl;
cout << title.value << endl;
return 0;
}Output is 4 then draft. vector and map in the next chapters are class templates of this kind, with more members and more rules.
Templates versus overloading
Overload when the bodies differ: one print for an int, another that loops through a list. Use a template when the body is the same and only the type changes. You can mix them later, but you do not need that mix to start.
auto on a variable is a related convenience: the compiler fills in the type of that one name. A template fills in types for a whole function or class you plan to reuse.
Put the template definition in the same file as the call for now, above main. Splitting templates across .h and .cpp files is a later linking topic. These examples stay in one file so g++ on /cpp/try can compile them as-is.
The library is built from templates
The Standard Template Library is named that for a reason. vector<int> is a class template. sort is a function template. The next chapter is a map of that library, not a dump of every header.
Worked examples
The short listings above are there so you can see the grammar. The programs here use the same statements on quantities that already have units: a speed, a pH, a count of bases. They are classroom numbers. Air resistance is ignored. g is 9.81 m/s² unless a line says otherwise.
Open them in the C++ editor at /cpp/try. Change one measurement and check whether the result still has the right unit.
Maths
The larger of two values
max is the same comparison for int or double. A function template writes that once. bigger(3, 9) is 9. bigger(2.5, 1.2) is 2.5. The compiler stamps out two functions.
max(a, b)
Example
#include <iostream>
using namespace std;
template <typename T>
T bigger(T a, T b) {
return a > b ? a : b;
}
int main() {
cout << bigger(3, 9) << endl;
cout << bigger(2.5, 1.2) << endl;
return 0;
}Physics
Clamp a reading
A sensor might report 12 when the legal range is 0 to 10. clamp is min(max(x, lo), hi). A template does it for int counts or double volts without two copies of the logic.
Example
#include <iostream>
using namespace std;
template <typename T>
T clamp_to(T x, T lo, T hi) {
if (x < lo) return lo;
if (x > hi) return hi;
return x;
}
int main() {
cout << clamp_to(12, 0, 10) << endl;
cout << clamp_to(3.3, 0.0, 5.0) << endl;
return 0;
}