T = ?1#include <iostream>2template <typename T>3T larger(T a, T b) {4 return a < b ? b : a;5}6int main() {7 auto i = larger(3, 7);8 auto d = larger(2.5, 1.5);9 std::cout << i << ' ' << d;10}T = intT = doublemain() framei int–d double–3, 72.5, 1.5intdouble72.53, 2.5!
Violet: the code, and the functions the compiler writes from the templateSand: the compiler (its face shows T); slate: main's variables i and dTokens: arguments go in, type stamps come out, results go to i and d; red means an errorLeft: the code larger.cpp. Middle: the compiler, showing what it deduced for T. Right: the functions it writes from the template. Front: main's variables i and d. Each call lets the compiler deduce T from the arguments and stamp out one real function per distinct T, at compile time. At run time only those ordinary functions are called. Each instantiation is separate machine code, so many different T can make a program bigger. Linkers merge identical instantiations made in different files.

The idea

  1. You want larger(a, b) for ints, for doubles, for strings. Without templates you write one copy per type, and every bug must be fixed in every copy. A template lets you write the idea once.

What the compiler does

Limits and uses

What happens

;; step 1/9 · copies
without templates: one overload per type
  int    larger(int a, int b)       { return a < b ? b : a; }
  double larger(double a, double b) { return a < b ? b : a; }
  std::string larger(std::string a, std::string b) { ... }
same body, different types: copy, paste, and keep them all in step
with a template: write the body once, for any type T

Deduction looks at each argument on its own. For larger(3, 2.5) the two arguments give int and double, so deduction fails and the template is not a candidate (the error says "deduced conflicting types for parameter 'T'"). No conversion is tried while deducing; it is tried only after T is fixed, as in larger<double>(3, 2.5). To instantiate a template the compiler must see its whole definition, so templates are usually defined in header files rather than split into a .h and a .cpp.