Variadic Templates – Transformations!

Wow, I just accidentally exposed another feature of Variadic Templates – you can transform them, and then create a new Variadic Template on-the-fly!  This is so cool!

Let me explain:

Given this call to TestVariadic:

  TestVariadic(0, 4, 'a', '\0', p, 0, "string");

and given this function:

template <typename... Args>
void TestVariadic(const Args&... args)
{
    std::cout << "vals (in reverse):" << std::endl;
    bool_variadic(boolizer(args)...);
}

We call (for each argument) ‘boolizer()’, which does nothing but return a true/false boolean value:

template <typename T>
bool boolizer(const T& val)
{
    std::cout <<  val << "	";
    return (val != 0);
}

Nothing fancy eh?  And note we’re working in reverse-order again (see my edit on last post), so we’ll see the list printed out right-to-left.  However, the cool thing is – we call a ‘bool_variadic()’ function with the return values from boolizer().  And this ain’t no ‘dummy()’ function.. it’s special =).  Here it is:

template <typename... Args>
void bool_variadic(const Args&... args)
{
    std::cout << "\nbool states (in FORWARD order):\n" << std::boolalpha;
    //dummy(reportBoolState(args)...);  // this'd be reverse order (right-to-left)
    reportBoolState(args...);
    std::cout << std::endl;
}

Okay, I know – more variadic template functions – annoying!!  But check it out – ‘reportBoolState()’ is a templated recursive function (well, not such a new thing), that ONLY operates on bool values (now we’re getting somewhere).  So here’s the two necessary functions required of any recursive variadic template design (non-variadic overload before the main val+variadic recursive func):

int reportBoolState(bool bVal)
{
    std::cout << bVal << "	";
    return 0;
}

template <typename... Args>
int reportBoolState(bool bVal, const Args&... args)
{
    std::cout << bVal << "	";
    reportBoolState(args...);
    return 0;
}

So, take a moment to gather this in.. We’ve literally transformed a set of varying types (that’d be the Args pack) into something completely different – a simple list of booleans!  That’s just awesome!  Oh.. and note that with the recursive variadic functions, we do actually move left-to-right, so the booleans are in the same order as the original variadic template list.(this is why the output doesn’t match up).  You could uncomment that ‘dummy’ line to see things in right-to-left order, however.  Man, this stuff is funn =)

Oh, and here’s the full example from above at Coliru’s online compiler.  Also available on Pastebin.com.

P.S. initializer_list’s are one of my other favorite new features – but quite limited in they only accept a compile-time-defined list of one type, and can’t be used dynamically with, say, a boolean list of variadic templates.. =P  (it’d be cool if someone proved me wrong though)

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.