Introduction

C++11 variadic templates are templates accepting any number of template parameters.

To understand the need for variadic templates, we’ll have to look at the history. As far as my research can tell, the first C compiler to support variadic methods was the WatCom C compiler from 1990s the first to support variable number of elements.

The concept of having variable number of elements, is much older. It’s a mathematical term for functions taking any number of parameters, like the sum of a group of numbers.

Previously, the most used variadic methods are the printf-family of methods. Those are used for output formatting of strings.

With C++11, the weakness with variadic methods are addressed with the introduction of variadic templates.

Unless great care is taken when writing C-style variadic methods, there is a great risk of using memory not intended for this particular method. printf family of methods, specify formatters in the first argument, and a number of arguments to format into the string. If the number of elements in the format string is greater than the supplied, a poorly written printf method may use memory after the method call. That memory may or may not contain passwords or other sensitive information.

Variadic templates

As with regular templates, there are both variadic class templates, and variadic function templates.

Variadic templates use the ellipsis (...) as the signature "keyword".

// Variadic methodtemplate<typename ... T>
void variadic_method()
{}

template<typename ... T>
class variadic_class
{};

Both of these do nothing, and can accept any number of template parameters. Either way, it only serves as a curious case, and it will be optimized away in any compiler.

sizeof…

There is a new sizeof() with the introduction of variadic templates, namely sizeof...().

The value is computed at compile time, and can be used in constant expressions (constexpr).

Variadic method in use

There are a couple of usage cases for variadic templates, and most of them are when there is a class acting as a proxy method between the calling code and the consumed class itself. A proxy can be a smart pointer (std::unique_ptr), or any other custom class encapsulating any other class.

Variadic template methods are used to construct these proxy classes by forwarding the arguments to the constructor. The unique_ptr is an excellent example of such a method.

This example doesn’t show it, but it beautifully joins several C++11 features into one simple use case. There is nothing special about to_be_made_unique. It’s a regular class with a regular constructor.

The line with auto ptr = std::make_unique<to_be_made_unique>(a, b, c); is where the beauty starts.

It will create a variable called ptr, which is declared auto. The compiler will at compile time, deduce auto ptr to std::unique_ptr<to_be_made_unique> ptr.

std::make_unique is called with template parameter to_be_made_unique and arguments a, b, c.

Behind the scenes, std::make_unique is a method accepting a variable number of parameters, which it will perfectly forward to the to_be_made_unique constructor, through variadic expansion.

Automatic resource cleanup. As ptr is a smart pointer, it will automatically delete the pointer when it goes out of scope.

And the best part of this, is that all this extra syntactic sugar will almost not incur any extra overhead at runtime. Most of this will make the compiler work a little extra, and it’ll produce cleaner machine code. The only extra cost, is the automatic deletion of the pointer when the smart pointer goes out of scope.

There is also no difference in runtime size when using std::unique_ptr versus a raw pointer. They will either be 32-bits or 64-bits, depending on the architecture you’re building for.

Variadic expansion

To be able to use variadics, one must understand how variadic expansion works.

This is a variadic method, which will then expand the arguments and call an appropriate method.

Storing the variadic pack without expanding it

Before C++11, there was only one readily available structure in the Standard to hold generic data, std::pair and it could only hold two values.

With C++11 comes std::tuple. It can hold any number of elements and is constructed by a variadic initializer through std::make_tuple. A tuple is a data structure consisting of multiple parts. It is comparable to a struct, but a field in a tuple is accessed by an index and not a name. A struct and a std::tuple with identical data, occupy identical space.

Empty tuples are allowed, and using a std::tuple is sort of a generic storage class. There is no need to implement one. But if there is a need of specializing such a generic storage class, here is a sample class.

Tuples are strongly typed

Even though tuples aren’t the focus of this chapter, there will be a brief section with how to use tuples. Tuples are strongly typed, and the length and types are checked at compile time.

To retrieve values from tuples, there is a method called std::get. The type returned from the tuple will be the same as we put into the tuple in the first place (except references have been stripped away, and so on).

The variable from_b is of type int, even though it’s constructed from a const int &.

Variadic function signature

When designing and implementing a variadic method, it’s important to know what’s really happening behind the scenes. When calling a variadic method with variadic_method(a, b, c), the (a, b, c)-part is packed into a pack in the method you’re calling.

Given this method signature:

template<typename ... T>
void variadic_method(T...args)

The parameters a, b, c are packed into args, which is a variadic pack. In the method above, the variadic pack is copied before it’s used. Methods in the standard library is using universal reference to forward the parameter pack.

To test the notion of copied vs. moved parameter packs, here is a class not_trivially_copyable which will print something when it’s constructed, copy constructed, move constructed and destructed.

Comments

Probably worth noting that gcc and clang provide __PRETTY_FUNCTION__ magic variable and Visual Studio provides __FUNCSIG__ macro that expands to the function signature. This can be useful in understanding and debugging. Links and example in my Stackoverflow answer here: http://stackoverflow.com/a/16338804/1708801