# Function and Class Templates — C++

Source: https://www.skillbyai.com/en/cpp/t-templates

> Write generic functions and classes with templates and understand instantiation.

## Code that works for many types

**Templates** let you write a function or class once for many types, with full static type checking. A **function template** such as `template <typename T> T max_of(T a, T b)` is a blueprint; when you call it with `int` or `double`, the compiler **instantiates** a specialised version for that type, so there is no run-time cost. The compiler usually **deduces** template arguments from the call; you can also specify them explicitly (`max_of<double>(3, 4.5)`). **Class templates** (`template <typename T> class Stack`) work the same way, and since C++17 **class template argument deduction** lets you write `std::vector v{1, 2, 3};`. Templates can also take **non-type parameters**, such as `std::array<int, 5>`. Because the compiler needs the full template definition to instantiate it, templates are normally defined **in headers**. The STL is built entirely on templates. Classic downsides are long compile times and famously long error messages, which **concepts** (next topic) greatly improve.

## One template, many instantiations

The compiler stamps out a concrete version of a template for each type it is used with.

![A stencil shape on the left with arrows to three solid copies of the shape in different colours on the right.](assets/figures/cpp/section-6-map.svg) — Figure 6.1 — Template instantiation for different types.

## A function template and a class template

The compiler generates code for each type actually used.

```cpp
#include <stdexcept>
#include <string>
#include <vector>

template <typename T>
const T& max_of(const T& a, const T& b) {
    return (a < b) ? b : a;
}

template <typename T>
class Stack {
public:
    void push(T value) { items_.push_back(std::move(value)); }
    T pop() {
        if (items_.empty()) throw std::out_of_range("pop from empty stack");
        T top = std::move(items_.back());
        items_.pop_back();
        return top;
    }
    [[nodiscard]] bool empty() const { return items_.empty(); }
private:
    std::vector<T> items_;
};

int main() {
    int a = max_of(3, 7);                               // instantiates max_of<int>
    std::string s = max_of(std::string{"pear"}, std::string{"apple"});   // max_of<std::string>
    Stack<std::string> undo;
    undo.push("typed hello");
    auto last = undo.pop();
}
```

## Templates live in headers

Putting a template's definition in a .cpp file and only its declaration in a header leads to "undefined reference" link errors, because other files cannot instantiate it. Define templates in headers (or use explicit instantiation for a known set of types).

**Quiz:** When does the compiler generate code for a function template?

- [ ] When the template is declared
- [ ] At run time
- [x] When it is used with specific types (instantiation)
- [ ] Only in debug builds

*Answer:* When it is used with specific types (instantiation). Templates are instantiated for each set of template arguments actually used.
