Friday 6 June 2008

Welcome to my blag!

Hello, boys and girls! Instead of writing my own wobsite, I came here... So it looks like today is the day when my blagging career starts. But before you dissolve in exalation, i must warn you: This is going to be a tech only blag! "What do you mean by tech only?", you might ask. Well, here is a list of things you should at least have heard of before trying to read it. (Ordered from least probably heard of to very likely heard of, bottom up:)
  • Electricity
  • Computers
  • Programs
  • Programming
  • C++
  • The upcoming Standard for C++

No idea of what I'm talking about at one of those points? Well, you're probably better off reading something else, otherwise you are in danger of serious injuries from your head banging against the keyboard when falling asleep momentarily! (-;

Sow, now that I'm the only reader of my own blag now, here's what I'm up to:
The International Standards Organisation (ISO) and the American National Standards Institue (ANSI) are currently working on an improved version of C++, that addresses many issues that came up after the first standard (back in 1998).
This new standard will probably be released about the beginning of 2009 [1].

And what I want to do is to write some kind of "introduction" for C++ programmers that want to become familiar with the new features of C++. Of course, before beginning to write about it, I should become familiar with the features myself.

Today I had nothing to do at work. And what does a geek do when he's bored and has access to a computer with an internet connection? That's right, he reads ANSI/ISO- Papers (-: Here's what I have been reading:
[2]: This paper describes a new feature called "variadic templates", that's going to ease template metaprogramming a lot. [3]: This document describes the changes to be made to the working draft and also contains a few revisions over the above document.

So what are "variadic templates"? Variadic templates are the possibility to pass a variable number of arguments to a template. Sounds familiar? Well, it's the compile time version of the varargs macro, which everybody instantly starts to hate at first sight. Where the varargs macros forces you to trust the users of your functions to pass the right types of arguments, and leaves a LOT of space for errors, the Variadic Templates feature lets you pass a variable number of arguments SAFELY! And by safely I mean a typesafe, completely compile time defined, zero overhead variable argument lists. Can you top that?

Well, I think it's time for code.


// overload a special case with no arguments
void printf(const char* s) 
{
    // stop on null character
    while (*s)
    {
        if ( *s == '%' && *++s != '%')
            // if we came here we ran out of arguments but not out of string
            throw std::runtime_error("Missing Arguments!");
            
        std::cout<< *s++;
    }
}

// case for variable arguments
template <typename T, typename... Args>
void printf(const char* s, T value, Args... args)
{
    while (*s)
    {
        if ( *s == '%' && *++s != '%') // if we encountered a formatting argument,
        {
            std::cout<<value; // print the value
            return printf(s, args...); // and call this function recursively
        }
        std::cout<< *s++;
    }
    
    // if code flow came to here, we ran out of string but not out of arguments
    throw std::runtime_error("Extra arguments");
}

This code is taken from [2], with a few adaptions and comments from me.

Allright, let's have a look at the declaration of the template: template<typename T, typename... Args> Here typename T is a regular template parameter, but typename... Args is the new stuff. This means that Args is a Parameter Pack. A parameter pack is a template argument that contains other arguments. The parameter pack has to be the last template parameter (of course), and can be also of an ordinary type.
Example: template <typename T, unsigned int... Integers> void do_something(Integers... ints) { ... }

If we again look at our printf example from above, we see that the ellipsis (...) is on the left side of the template Parameter. This means that we pack all template arguments into Args. Args is now a pack of Types. The ellipsis to the right of Args, in the parameter list of the function itself means that we unpack the types in the parameter pack. At the same time, we pack the arguments for the function into args. is now a pack of values. This pack of values is finally unpacked in the recursive call to printf.

As you see, we packed a set of Types and then we unpacked it. When unpacking the set of Types, we packed the actual values, that will be passed to the function. Later we unpacked the values, to pass them to another function.

But there is a problem. The only way to unpack Template Parameter Packs is either as Types for function arguments or as arguments for another template. Function argument packs can only be unpacked for calling another function. Although there is the possibility to count the number of arguments in the Template or Function Parameter Pack with the sizeof..() operator: template <typename... Args> void print_nargs(Args... args) { std::cout<<sizeof...(Args); } there is no way to iterate through the parameters with an ordinary loop like with the varargs macro. However you can still handle the arguments one by one: by using recursion.
We allready have seen how this is done above. The trick is performed by providing one fixed Template argument, and calling the same function again, with the remaining arguments. This will cause the first argument to be "stripped off", so you can use it. Depending on what you want to do, you might have to provide a specialization or overload for an instantiation with no template arguments (as you can see above).

So what's it for? This new feature can be used for functions with variable argument lists, such as printf, but also for passing on arguments to constructors, callback funcions and so on. Variadic templates are particular useful in conjunction with the new initializer lists. An important application for variadic templates is the area of template metaprogramming. Whereas you might not come in touch with it directly, it may well be that you will use one of the libraries written with this technique, such as various Boost libraries. Until now, variable arguments were realized either with templates which had a lot of default arguments or by (mis)using the preprocessor, which causes awfull and unmaintanable code. With this feature, library authors have now a great tool at their hands. We will see, what will emerge from that.

Well, that was a rather short Introduction into variadic templates. Look back here in some time, I will post a more detailed introduction in some time. Until then, you can read [2] and [4], as "accompanying literature".

I hope someone read this, and I welcome every (usefull) comment. If have questions, write me an email, maybe I'll answer it (-: Here are the links: [1]: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2565.html [2]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2080.pdf [3]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2152.pdf [4]: http://www.osl.iu.edu/~dgregor/cpp/variadic-templates.html

No comments: