Variadic template fun

So I’ve been messing around with Variadic Templates in C++11 recently, and have been blown away but what I can do with this feature.  Its not just about those lame recursive ‘print’ examples, or in-place construction (see emplace) – nooo, there’s far more to it than that! Once you understand a little about what can be injected into the ‘unpacking’ of these variadic template parameters, you’ll start thinking up way cool stuff.

For example, look at the below snippet:

inline void dummy(...) {}

template
void TestVariadic(const Args&... args)
{
    int n = 0;
    dummy(repeater(n, args)...);

    std::cout << "\nValue of n:" << n << std::endl;
}

That ‘dummy’ function, for some reason or another, is required in order to use this special form of ‘…’.  When ‘…’ is outside of the function call, it means the given function is called once for each and every argument (and type).  This is as opposed to using the ‘…’ inside of the function (by the args var), which just expands and forwards unpacked variadic template variables as extra parameters. (sorry if I’m not too clear on the wording, its f’ing confusing).

As I mentioned, the ‘dummy’ function needs to be there to convince the compiler to do multiple function calls.  An additional requirement is that the ‘repeater’ function must also return a value so that the compiler sees that you are actually passing something to dummy().  It’s pretty annoying, and I’d very much like to do repeater(n, args)…; but its not possible with the standard the way it is.

Anyway, the unique bonus of doing a repeater function is that you can pass pointers or references to local variables, etc, for each repetition.  This is where I see variadic templates being the most useful, especially to me.  For the above, the repeater could be as simple as this:

template
int repeater(int &n, const T& val)
{
    std::cout << '.';
    ++n;
    // Silence compiler warnings about unused val:
    (void)val;
    return 0;
}

Here I’m just incrementing ‘n’ and returning a value that will be thrown away by ‘dummy’.  This also prints a silly ‘.’ output each time its called.  The nice thing to notice though is that there is only one template argument required for each call to this function, and that I am actively modifying the calling function’s ‘n’ value.

Perhaps it’s not quite clear from this context just how powerful this is, but once you start down this path, hopefully you’ll begin imagining all kinds of wild tricks that can be done.

The ‘trick’ I personally got to work with variadic templates is a type of comma-separated ‘printf’ call that creates all the “%xx” format strings, puts them in an array along with the matching values, and makes one call to vprintf.  And suprisingly, with Mirosoft VC++ 2012 (November CTP) compiler, the code that is generated is super efficient – as in, nearly as good as typing out the complete printf() call yourself, and very close to the space needed for cout calls.

MSVC++ takes my template metaprogramming mess and optimizes away any calls and directly embeds a complete string-assembly sequence plus value stack assembly inline!  Plus, in timed results on both GCC and MSVC, variadic-printf beats out cout calls quite consistently.  It’s really quite cool.

Anyway, if you’d like to start experimenting, I’ve put a simple but more complete example of the above on the ‘Coliru Editor’ page, which is an actual live C++ editor linked to a G++ 4.7 C++11 compiler (running on a unix box). Fun stuff! (example also now available on Pastebin.com)

Now.. back to obsessing about other things..

Edit:  Note, one of the issues with using that dummy(…) function is that the compiler will work through the arguments backwards..  the reason for this is that a function accepting a variable number of arguments is called with each argument pushed from right-to-left.

That means that the return from the right-most parameter must be retrieved before it can be pushed – which typically winds up calling that function first.  It’s not recommended to rely on this, though – as the C/C++ standards say that the evaluation of each parameter can happen in any order.  Only the order they are pushed on the stack is guaranteed.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s