Templates: write it once, for any type
A function template is a recipe with a blank: the type parameter T. It is not a function yet. When you call it, the compiler works out T from the arguments and writes a real function for that type, once per type, before the program ever runs. Follow larger(3, 7) and larger(2.5, 1.5) as the compiler deduces T, stamps out larger<int> and larger<double>, and see what happens when deduction fails and how C++20 concepts state what T must support.
5 quick questions
Pick an answer to see why. Your score saves with your progress.
01template <typename T> T larger(T a, T b) { return a < b ? b : a; } is in a file, but nothing calls larger. How many functions does the compiler make from it?
A template is instantiated only when it is used. With no call, no larger<...> function is written and no machine code is made for it.
02What does the compiler deduce T to be in larger(2.5, 1.5)?
2.5 and 1.5 are double literals, and both parameters are plain T, so deduction gives T = double and the compiler instantiates larger<double>.
03A program calls larger(3, 7), larger(1, 2) and larger(2.5, 1.5). How many functions does the compiler make from the template?
There is one instantiation per distinct T. Both int calls use larger<int>; the double call needs larger<double>.
04Why does larger(3, 2.5) fail to compile, and what fixes it?
Each argument is deduced on its own and the results must agree. Naming T yourself skips deduction, and 3 is then converted to 3.0. (larger(3.0, 2.5) also works, because both are double.)
05What does template <std::totally_ordered T> add compared with template <typename T>?
A concept is a named requirement on T, checked at the call. Without it, a type that lacks < still fails, but the error appears inside the template body.
Glossary
- Template
- A recipe for functions or classes with one or more blanks (template parameters) that the compiler fills in when the template is used.
- Template parameter
- A stand-in in a template, written template <typename T>; T names a type that is chosen later.
- Template argument deduction
- The compiler working out a template's parameters from the types of the call's arguments, so you rarely write them yourself.
- Instantiation
- The compiler writing a real function or class from a template, with the parameters filled in, such as larger<int> from larger<T>.
- Function template
- A template that makes functions, such as larger or std::max.
- Class template
- A template that makes classes, such as std::vector<T> or std::unique_ptr<T>.
- Concept
- A C++20 named requirement on a template parameter, such as std::totally_ordered<T>, checked where the template is used.
Notes and sources
- The card is real C++20. It compiles with g++ or clang++ -std=c++20 -Wall -Wextra with no warnings and prints 7 2.5. Listing its object file's symbols (nm -C) shows exactly two functions made from the template: larger<int>(int, int) and larger<double>(double, double).
- 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.
- Each instantiation is separate machine code, so many different T can make a program bigger. Linkers merge identical instantiations made in different files.
- larger returns a < b ? b : a, the same rule std::max uses: when the two are equal it returns a. std::max takes and returns const references; this version copies, which is fine for small types.
- Concepts arrived in C++20. std::totally_ordered<T> requires all of <, >, <=, >=, == and != on T. Without a concept the template still works for any type that has <; the error for one that lacks it just appears inside the template body.
- cppreference.com: Templates
- cppreference.com: Function template (instantiation)
- cppreference.com: Template argument deduction
- cppreference.com: Template parameters and template arguments
- cppreference.com: Constraints and concepts (C++20)
- cppreference.com: std::totally_ordered
- cppreference.com: std::max
- cppreference.com: std::vector
- Standard C++ Foundation (isocpp.org): Templates FAQ
- C++ Core Guidelines (isocpp.github.io): T: Templates and generic programming
Quiz Unlocks after the last step.