Variadic Templates in C++ 11 (Part 2 of 2)

Last week we started discussing C++11’s new Variadic Templates.

In that article I showed you how to declare a function initialized by a Variadic Template that returns the number of template arguments it was called with. Today, we build on those concepts to implement a printf-like function with the properties of being typesafe, don’t requiring parsing formatting characters and supporting non-POD data types. Let’s get started.

The first thing I want to do is rewrite the example from last week. This will ease introducing this week’s concepts. Let’s create a new function g that does the same that f did, but receives any number of arguments via template instantiation.

template <class... T>
size_t g(T... args)
{
  return sizeof...(args);
}

g does exactly the same that f, the only difference is that we can now call it using the following syntax:

int main(int argc, char* argv[])
{
  cout << g(); // prints "0"
  cout << g(1); // prints "1"
  cout << g(1,2,3,4,5,6,7) // prints "7"
}

It is, in a way, like a variadic function, but written in C++11 style instead of plain C.

It’s important that you understand how g works, if you don’t, please review the code again and try making changes to it.

Assuming that’s out of the way, let’s delve in today’s article.

We want to develop a print function that can receive any number of parameters of any type. So we can call:


A a; // Create some object...

print(1);
print(1, 2.0f);
print(1, 2.0f, "Hello");
print(1, 2.0f, "Hello", a);

// An so on...

Now, you might be guessing that one way to implement this function would be to have a “base case” that can print one argument and then have it called with each supplied argument.

template <class T>
void print(const T& msg)
{
  cout << msg << " ";
}

That’s a really good idea and, last time, we saw how to determine how many arguments a Variadic Template has been instanciated with (using the sizeof… operator).

Unfortunately, when it comes to Variadic Templates, we can’t iterate over the arguments based on the count. We need to find another way.

In an idea that I regard largely borrowed from functional programming, what if we could separate the list of arguments in the “head” element and the “rest” of the list?

Well, if that was the case, then we could call our base-case print function with the head and then call the general-case function with the rest of the list. Eventually, the list will be empty and we will have printed all elements!

We can do exactly that using C++11 new template syntax:


// This is our base-case for the print function:

template <class T>
void print(const T& msg)
{
  cout << msg << " ";
}


// And this is the recursive case:

template <class A, class... B>
void print(A head, B... tail)
{
  print(head);
  print(tail...);
}

Let’s try this with a simple program:

int main(int argc, char* argv[])
{

  print(1, "\n");
  print(1, 2.0f, "\n");
  print(1, 2.0f, "Hello", "\n");

  return 0;
}

The output should be something like:

 1 
 1 2 
 1 2 Hello

And that’s all there is to it. The C++ compiler will take care of generating the appropriate code to instanciate our functions and to split the parameter list so we can print the arguments one by one. Notice how this is much easier than having to mess with variadic functions, while being typesafe too.

The biggest challenge is assimilating the new syntax, but there are lots of good references around like this article from IBM, where I got the idea of writing a print function, or even the Variadic Template proposal for the ISO committee, another great resource.

Stay tuned for more C++11 goodness next week!