# Chapter 14 - Notes - Variadic Templates

## Variadic Templates

{% hint style="info" %}
The following content is provided by Kevin Ushey.&#x20;

<https://kevinushey.github.io/blog/2016/01/27/introduction-to-c++-variadic-templates/>
{% endhint %}

**Variadic templates** are the only way of implementing **variadic functions** in C++. Variadic functions are simply functions that accept an **unspecified number of elements**.&#x20;

### Motivation

Consider the following problem statement: if we have a `sum` function that sums two integers:

```cpp
int sum(int a, int b);
```

We may later also want a `sum` function that sums three integers, and four integers, so on so forth. The only way we know how to this to our current knowledge is with function overloading:

```cpp
int sum(int a, int b, int c);  // Three elements
int sum(int a, int b, int c, int d);  // Four elements 
```

However this way of doing things is quite terse, and requires you to maintain a bunch of functions that do the same thing.&#x20;

This is where **variadic templates** come in handy.

### Syntax&#x20;

The syntax of a variadic template is most confusing the first time you see it. Consider the following simple example:

```cpp
template <typename... Ts>
void ignore(Ts... ts) {}
```

The variadic function `ignore` at the moment does nothing (empty function body). Let's dissect its syntax:

`template <typename... Ts>`

* `typename... Ts` declares `Ts` as a **template parameter pack**.&#x20;
* You will often see the naming conventions for these in the form of plurals, e.g. `Ts`, meaning multiple `T`s. Other common names are `Args` or `Rest`.
* The key part is the ellipsis operator (`...`) denoting that `Ts` is indeed a template parameter pack.&#x20;

`void ignore(Ts... ts)`

* This is the function signature, which accepts a **function parameter pack** (`Ts... ts`), i.e. a bag of parameters.
* The type of the elements in the function parameter pack are given by the **template parameter pack**.
* The key part is the ellipsis operator (`...`) denoting that `ts` refers to the template parameter pack.&#x20;

It may be useful to be able to *mentally* unwrap the above definition as:

```cpp
template <typename T1, typename T2, ..., typename Tn>
void ignore(T1 t1, T2 t2, ... Tn tn) {};
```

Following this, it should be clear that each value in the template parameter pack can be a different type:

```cpp
ignore(1, 2.0, true);
```

Has the same effect as:

```cpp
ignore<int, double, bool>(1, 2.0, true);
```

### Usage&#x20;

Let's attempt to implement a variadic sum function, as we so desired. You may expect the function to look like the following:

```cpp
template <typename... Ts>
double sum(Ts... ts) {
    double result = 0.0;
    for (auto el : ts)
        result += el;
    return result;
}
```

Unfortunately when it comes to variadic functions, you can't approach the problem in a standard iterative C++ style. You will need to write the variadic functions themselves **recursively** - with a **base case** and a **recursive case**:

```cpp
// The base case: we just have a single number.
template <typename T>
double sum(T t) {
  return t;
}

// The recursive case: we take a number, alongside
// some other numbers, and produce their sum.
template <typename T, typename... Rest>
double sum(T t, Rest... rest) {
  return t + sum(rest...);
}
```

The base case accepts one argument `T`.

The recursive case accepts **one or more** arguments, `T` and `Rest` (recall that a template parameter pack can be empty).

### Mechanism

How exactly does this work? Let’s trace what happens when we try to call, for example, `sum(1.0, 2.0, 3.0)`. This is going to be a bit repetitive, but it’s worth it to walk through the process at least once.

1. The compiler generates code for `sum(1.0, 2.0, 3.0)`. There are two competing overloads for `sum` here: the base case, and the recursive case. Since we’re passing in three arguments, the base case does not apply (it only accepts a single argument), so we select the recursive case.
2. Type deduction is performed – the compiler deduces `T = double`, and puts the rest in our parameter pack, with `Rest = <double, double>`.
3. The compiler generates code for `t + sum(rest...)`. It sees the recursive call to `sum(rest...)`. Note the use of `...` to ‘unpack’ the template argument – this has the effect of transforming `sum(rest...)` to `sum(2.0, 3.0)`.
4. The compiler generates code for `sum(2.0, 3.0)`. As in the first case, there are two competing overloads: the base case, and the recursive case. The base case once again does not apply as we have more than one argument, so we select the recursive case.
5. Type deduction is performed – the compiler deduces `T = double`, and `Rest = <double>`. It’s subtle, but notice that we have now unpacked our original `<double, double>` pack to `T = double` and `Rest = <double>`.
6. The compiler generates code for `t + sum(rest...)`. It sees the recursive call to `sum(rest...)` – this time, with `sum(rest...)` expanding to simply `sum(3.0)`.
7. The compiler generates code for `sum(3.0)`. We have now finally hit our base case: the overload taking only `T` is more specialized, relative to the overload taking both `T` and `Ts...`. The compiler generates code for the base case, and we’re done with the recursion.

Let’s outline the main techniques we’ve learned here:

* To unpack a parameter pack, use a templated function taking one (or more) parameters explicitly, and the ‘rest’ of the parameters as a template parameter pack.
* Recurse towards a base case: call your recursive function with the ‘rest…’ arguments, and let the compiler unpack your parameters in subsequent calls to your recursive function.
* Allow your base case to overload your recursive case – it will be selected in preference to the recursive case as soon as the parameter pack is empty.

### Conclusion&#x20;

We’ve outlined some of the basic tools and patterns for implementing variadic functions:

* Use recursion to implement variadic functions – implement a base case, and a recursive case, and have the recursive case reduce to a base case call;
* Use `...` to unpack parameter packs, or in more clever contexts, to unpack whole expressions containing a parameter pack.
