The idea
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.
Line 2 starts a function template. T is a template parameter: a stand-in for a type, filled in later. Lines 3 to 5 are a recipe for a function, not a function. On its own it makes no machine code.
What the compiler does
Line 7 calls larger(3, 7). Both arguments are int, so the compiler deduces T = int. This is template argument deduction: the argument types fill in the blank, so you rarely write T yourself.
Now the compiler writes a real function from the recipe, with every T replaced by int: larger<int>. This is called instantiation. It happens at compile time, and larger<int> is then compiled like any function you wrote by hand.
Line 8 passes two doubles, so T = double and the compiler stamps out a second, separate function: larger<double>. Each different T gets its own copy. Another call with ints would reuse larger<int>.
When the program runs, no template is left: main calls two ordinary functions. larger<int> gives 7 to i, larger<double> gives 2.5 to d, and line 9 prints 7 2.5. Each call costs the same as a hand-written function.
Limits and uses
Suppose you write larger(3, 2.5). From 3 the compiler deduces T = int, from 2.5 T = double. T cannot be both, so it is a compile error. Name the type yourself: larger<double>(3, 2.5) turns 3 into 3.0.
The recipe uses a < b, so T must support <. Call larger with a type that lacks it and the error points inside the template. C++20 concepts state the rule up front: template <std::totally_ordered T>.
The standard library is built from templates. std::vector<int> and std::unique_ptr<T> are class templates; std::max and std::sort are function templates. Each is written once and instantiated for the types you use.
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.