Concepts / Variadic Templates

Variadic Templates

Flexibility and checking cost come from one design choice. A library component that gains generality through variadic parameters gains reuse, and it also takes on the work of describing its valid interface in template code.

  • Programming

A Template That Does Not Fix Its Argument Count

Suppose you want one piece of code that works whether a caller passes one value, five values, or none at all. A template that always expects the same fixed list of parameters cannot do this without help. Variadic templates, sometimes just called variadics, solve the problem by accepting a varying number of arguments. That flexibility is the reason to use them, but it also creates a cost that you must understand before using them well.

What do you think happens?

A template declares exactly two parameters. How many arguments can a caller pass to it?

Reveal answer
Answer:

Exactly two. That version can only be used with two arguments.

A fixed template's declaration sets its argument count. A variadic template is different: its declaration does not fix the count, so the count is decided by each call.

A Single Slot for a Whole Argument Line

A helpful way to picture a variadic template is as a single slot that takes a whole line of arguments, rather than a row of labeled boxes. The key word in the idea is any. A variadic template is not limited to one specific argument count. It can be given two arguments, or ten, or none, as long as the arguments are acceptable to it.

Argument listset by the callPosition 01Position 1aPosition 22.5holdsholdsholds
How do the separate arguments in a call like f(1, a, 2.5) line up with the single list and its positions? The three arguments occupy positions 0, 1 and 2 of one list, and the list length is set by this call alone.

The arguments in this made-up call do not need to share a type. One is a whole number, one is a character, and one is a decimal value. The number of positions is decided by the call, not by the template's declaration. The diagram above is a made-up call used only to show how the positions line up.

Why the Same Template Takes Different Calls

If the same template were called with only one argument, the list would have a single position. If it were called with none, the list would be empty. In each case the template is the same; only the call changes. This separation between the template and the particular call is what gives variadic templates their reach.

Worked example

One template, three calls

A single variadic template is called three different ways. For each call, determine how many positions the argument list has and whether the arguments must share a type.

  1. 1
    Call 1: one argument

    The call passes a single value, so the argument list has one position. The template itself has not changed.

  2. 2
    Call 2: three arguments

    The call passes 1, a and 2.5. The list now has three positions, holding values of different types.

  3. 3
    Call 3: no arguments

    The call passes nothing, so the argument list is empty and has no positions.

  4. 4
    Compare the calls

    The declaration never changed across the three calls. Only the number of arguments supplied by each call changed.

Result

The argument count comes from each call. The template declaration stays the same, and the arguments do not need to share one type.

The Strength and the Weakness Together

The central statement about variadic templates has two halves. Their strength is that they can accept any arguments you care to give them. Their weakness is that checking the types of their interface can be a possibly elaborate template program. These two halves describe the same design choice from two angles, so they should be understood together rather than as separate facts.

Declared parametersExactly twoArgument countFixed by the declarationRules locationVisible parameter listParameter packAny numberArgument countSet by each callRules locationTemplate checking logicdeterminesrules indeterminesrules in
How does the set of valid signatures differ between a fixed template and a variadic one? The fixed version lists its rules in a visible parameter list, while the variadic version moves many of those rules into its own checking logic.

Mistakes Beginners Make with Variadics

  • Common mistake

    Assuming every argument must have the same type

    What it looks like

    A call passes a whole number, a character and a decimal value in one argument list.

    Why it fails

    The arguments do not need to share a type. The number of positions is decided by the call, and the positions are not forced into one type.

    Do this instead

    Read the argument list as a line of values that may differ in kind, and check each one against the rules of the interface.

  • Common mistake

    Assuming a variadic template accepts any arguments at all without checking

    What it looks like

    A caller passes many values to a variadic template and expects it to work regardless of what they are.

    Why it fails

    The template accepts any arguments you care to give it, as long as the arguments are acceptable to it. The openness of the call is paired with checking logic inside the template.

    Do this instead

    Treat the template's checking logic as the place where acceptable arguments are defined.

  • Common mistake

    Treating the flexibility as free

    What it looks like

    A developer adds a variadic parameter to a template and assumes its interface is as easy to verify as a fixed one.

    Why it fails

    The openness that lets a caller pass any arguments forces the template to carry more of the burden of deciding what counts as a valid interface.

    Do this instead

    Budget time for writing and understanding the checking logic whenever a template accepts a varying number of arguments.

  • Common mistake

    Confusing the template with a particular call: the template stays the same while each call supplies its own number of arguments.

Why the Standard Library Relies on Them

Because of their flexibility, variadic templates are widely used in the standard library. The reasoning is direct. A library is meant to serve many different callers, and those callers will not all want to pass the same number of arguments. A component that accepts any arguments can be reused in more situations than one that fixes its argument count in advance.

The same connection explains why the weakness is worth studying. The components that benefit most from flexibility are exactly the ones whose interfaces have to be checked carefully. When you read library-style code, its generality was bought with template logic that the designer had to write.

Key point

Flexibility and checking cost come from one design choice. A library component that gains generality through variadic parameters gains reuse, and it also takes on the work of describing its valid interface in template code.

Practice Tracing a Variadic Call

EASY

A variadic template is called with four arguments: the whole number 7, the character x, the decimal value 0.5, and the whole number 9. Describe the argument list the template receives. How many positions does it have, and does the template's declaration need to change for this call compared with a call that passes only one argument?

Hints
  • Count the arguments in the call, since the call sets the number of positions.
  • Remember that the arguments do not need to share a type.
  • Think about whether the template is the same across calls with different counts.
MEDIUM

Explain in your own words why checking a variadic template's interface is harder than checking a fixed one, and name the two places where the rules for valid calls can live.

Hints
  • Consider what the caller is allowed to supply in each case.
  • Think about where the template describes which calls are acceptable.

Key Takeaways

  • A variadic template accepts any number of arguments, and the argument count is set by each call rather than by the declaration.
  • The same template can receive one argument, several arguments of different types, or none at all.
  • The flexibility that lets callers pass any arguments is the same choice that makes checking the interface a possibly elaborate template program.
  • Variadic templates are widely used in the standard library because a library must serve callers who want different argument counts.

Related concepts

More concepts starting with V