In this article we’re going to look at a new feature of templates in C++11 – the concept of the variadic template.
Variadic templates allow us to create functions and classes, not only with generic types, but also a variable number of generic types.
If you haven’t been following along with the template articles, I’d suggest you read this article first before continuing.
The problem (so far)
Previously, we used a template constructor on a template class to allow us to construct a base class with a variable number of constructor parameters of different types. Here’s where we got to:
Our Named class allows us to prepend a name string to any class that implements the display() method. In order to deal with (template parameter) classes that have non-default constructors we have provided the Named class with a template constructor function. This function has been overloaded to handle base classes with two and three (template) parameters. Given the classes below, our Named class works just fine:
The code as it currently stands means we’ll have to overload the Named constructor every time we use a base class with a different number of parameters. This will quickly become onerous.
We need a more elegant solution.
A variadic template is a template which can take an arbitrary number of template arguments, of any type. Both classes and functions can be variadic.
Below, I’ve replaced our overloaded constructors with a variadic version.
The … operator has two roles. When it occurs to the left of the name of a parameter, it declares a parameter pack. By using the parameter pack, user can bind zero or more arguments to the variadic template parameters. Parameter packs can also be used for non-type parameters.
By contrast, when the … operator occurs to the right of a template or function call argument, it unpacks the parameter packs into separate arguments.
In practice, the use of the … operator in the code means that the whole expression that precedes the … operator will be repeated for every next argument unpacked from the argument pack, and all these expressions will be separated by a comma.
Now, the compiler will use the variadic template to construct the appropriate constructor for the type of base class being instantiated.
Here the compiler deduces not only the types of the template parameters from the call, but also the number of template parameters required. This is used to construct a version of the template constructor with the appropriate number of template parameters.
Using variadic templates, the compiler is doing the task we were performing earlier by creating the appropriate template overloads for our class. However, unlike us, the compiler doesn’t have to provide overloads for an arbitrary number of template parameters, just in case – it can create only the overloads it needs for this system.
This mechanism is a much more elegant way of creating generic objects, particularly in library code when it cannot be known a priori the nature of the classes that will be used as template parameters.