TR1's tuple class template allows you to pack an arbitrary number of objects with arbitrary types in a single container-like object. The underlying implementation of class templates that take a variable number of arguments in contemporary C++ is problematic and limiting, though. The addition of variadic templates to C++0x will make the implementation of such classes much simpler, ridding library implementers of many of the limitations and performance bottlenecks that they are facing today. Let's examine variadic templates in detail.
The canonical example that demonstrates the need for variadic templates in C++ is class tuple:
tuple<int, float> t2;
tuple<char, string, short, double> t4;
Tuples set an arbitrary limit on the number of arguments they can store. According to the C++0x standard, the minimum number of elements allowed is 10. The reason for specifying such a low minimum is that implementers are unable to directly express in contemporary C++ the notion that a function or class template takes an arbitrary number of arguments. Instead, they use various emulations, including extra defaulted template parameters and preprocessor metaprogramming (Yes, macros are back with a vengeance!). Using the preprocessor to emulate "variadic" templates eliminates a large amount of code duplication that would occur otherwise. However, it comes with many problems. Take for example the std::tr1::function class. The original GCC implementation of that class supported 20 parameters but the excessive compilation time forced the implementers to revert to a maximum of 10 parameters instead. Even with 10 parameters, the code of std::tr1::function still requires too much time to preprocess and parse. In addition, it's nearly unintelligible. Let's look at a concrete example.
To implement a tuple that accepts up to 10 parameters of unrelated types, library vendors use default template parameters, with a dummy struct serving as default value for every parameter:
struct unused;
template<typename T1 = unused, typename T2 = unused, typename T3 = unused,
template<//_ up to _N parameters
typename TN = unused> class tuple;
This tuple can be used with anywhere from zero to n template arguments. However, most of the specializations of that class template will have a large number of unused arguments:
tuple <char, short, int, long long> eightosixtyfourbits;
Here, six template parameters are unused, but they still lead to long compilation times and cryptic compilation errors. One way to optimize the compiler-generated code of such classes is to provide a list of partial specializations as follows:
template<>
class tuple<> { /* zero-argument version*/ };
template<typename T1>
class tuple<T1> { /* single argument version*/ };
template<typename T1, typename T2>
class tuple<T1, T2> { /* two-argument version*/ };
This trick ensures that the code produced for a given number of arguments is optimized and correct. However, it also leads to a huge amount of code repetition and extremely long type names in error messages (many compilers print the defaulted arguments anyway). There is a more serious flaw with this approach -- the fixed upper limit on the number of arguments that can be provided.
To solve these problems, a new C++0x feature called variadic templates was voted into the Working Paper some time ago. Let's see which advantages variadic templates offer.
C++0x variadic templates provide an intuitive and efficient mechanism for expressing function and class templates that take an arbitrary number of arguments (in this part I will focus only on variadic class templates). The authors of the variadic templates proposal specifically designed this feature to eliminate the need for most uses of preprocessor meta-programming. In addition, variadic templates are type-safe and improve argument forwarding.
Using this new feature, you can explicitly state that tuple accepts one or more template parameters like this:
template<typename... Elements> class tuple;
The ellipsis (which you probably recognize from printf()-style variable arguments function declarations) to the left of Elements indicates that Elements is a template type parameter pack. A parameter pack is a new notion. Unlike an ordinary parameter, which can only bind to a single argument, a parameter pack is a single identifier grouping zero or more template arguments. Thus, in the following typedef declaration:
typedef tuple <char, short, int, long long> eightosixtyfourbits;
The parameter pack Elements binds to a list of arguments: char, short, int and long long whereas in this declaration, the parameter pack Elements binds to three arguments:
typedef tuple <float, double, long double> floating_point;
In the next part of this series, I will show how to unpack a parameter pack and present variadic function templates.
Será um bom incremento, já que muito provavelmente variadic templates
não será _retirado_ do draft do C++0x. :-)
:p.
O unpack dos parâmetros acontece através da especialização parcial do
template. O processo é um típico processo recursivo, em que uma
especialização total para a "lista vazia" e uma especialização parcial
para "elemento, resto da lista" são providenciadas. Quando o template
é usado com uma lista não-vazia de argumentos de template, a
especialização parcial "elemento, resto da lista" é selecionada; esta
especialização deve fazer uso do elemento e instanciar-se novamente
com o resto da lista; eventualmente a lista se tornará vazia e a
especialização total será selecionada.
O GCC 4.3 possui uma implementação de variadic templates acessível com
o flag --std=gnu++0x na linha de comando.
Rapaz, valeu Pedro, entendi mais ou menos o que você falou, mas não
tinha conseguido "visualizar" nada como ficaria o codigo.
Por isso dei uma procuradinha extra :D.
http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html
Esse link explica e demostra o "variadic template" melhor, para quem
quiser "ver" :D.