C++ Template Magic : template<T1, T2, … , Tn>

One of the most fascinating and equally ugly thing about C++ is template meta-programming. Templates and meta programming have given C++ library developers an unique advantage in expanding the expressivity of the library yet containing the runtime cost by resolving most of the otherwise runtime expense at compile time. Some of the most popular general purpose libraries that use templates extensively are STL and boost. I love the convenience of STL and use it widely in my personal and professional programming and personally advocate it too. I am fan of boost library in general for the clean component design and adoption of various design patterns into its library — for example the implementation of pro-actor model for its boost asynchronous library.  I like reading boost codebase, and I actively leverage boost libraries when appropriate. But there are times I feel certain components of the library is just too cumbersome for general use like the preprocessor library.

One of the limitations of templates (there are quiet of few) is the lack language expressivity for n number of generic type. There is the variable template definition but that is more like the variable argument with C functions. For, example I cannot define something like

template<class T1, class T2, … , class Tn>
struct tuple(T1 t1, T2 t1, … ,Tn tn);

Tuple<T1,T2,…,Tn> make_tuple(T1 t1, T2 t2, …, Tn tn)
{
    return Tuple(t1, t2, …, tn);
}

Unfortunately, semantic like this is inherently not there in the language, and understandably so. But there are lots of scenario that require programming provisions like this. I would also like my code to be extremely contained and readable even by someone who does not entirely understand the nuts-and-bolts of template programming and/or the boost preprocessor library. I have to lower my expectation from the language and shoot for something more achievable. I would be happy with a programming semantic for n template argument that is similar to template programming with a single generic. Something like,

template<TDEF(class T)> struct Tuple(TENUM(T));

template<TDEF(T)>
Tuple<TENUM(T)>
make_tuple(TPARAM(T,t))
{
    return Tuple<TENUM(T)>(TARG(t));
}

Unfortunate something like this too is not possible without making changes to the language grammar and modifying compiler implementation to auto detect the number of params to compile for. We can either indulge in the idealistic pursuit of changing the entire world or pragmatically we can keep the cleanliness of code but take some compromise to realize it with the existing provisions. As a library implementor it is not possible to predict the maximum number of parameters required, so we can handoff that design aspect to the application developer who should be knowing the answer to that question.

So, we could redefine this as

#include "tdef.h"

#define TUPLE(n)                                      \
template<TDEF(T,n)>                                   \
struct Tuple##n(TENUM(T,n));                          \
                                                      \
template<TDEF(T,n)>                                   \
Tuple##n<TENUM(T,n)>                                  \
make_tuple(TPARAM(T,t,n))                             \
{                                                     \
    return Tuple<TENUM(T)>(TARG(t,n));                \
}                                                     \

// define function upto 4 param
// We will leave it to the user of the library to
// specify the count
DEF_FN(Tuple, 4)

Very unfortunately we have to wrap the entire class definition under a #define. This would take away the ease of debugging since the compiler will not point to the line numbers under the #define.  Anyways, template magic was never for the faintest of the heart.  Now comes the question of how do we write something like TDEF and TENUM. Boost pre processor library has already solved these problems rather extensively by employing recursion with #define. We will keep it simple and declare the following as below.

#define TDEF(T,n) TDEF_I_##n(T)
#define TDEF_I_1(T) class T1
#define TDEF_I_2(T) class T##2 COMMA TDEF_I_1(T)
#define TDEF_I_3(T) class T##3 COMMA TDEF_I_2(T)
…

#define DEF_FN(fn,n) DEF_I_FN##n(fn)
#define DEF_FN_I_1(fn) fn(1)
#define DEF_FN_I_2(fn) fn(2) DEF_FN_I_1(fn)
…

We can wrap the ugly #defines under tdef.h.

This is nowhere close to perfect, but at the least I am not stuck. There are still some (more !) ugliness with the naming of classes. We have to suffix a number to them depending upon the number of arguments they take (another template limitation, you cannot overload class names with different template arguments). The Tuple function will be declared as Tuple1<T1>, Tuple2<T1,T2> and so forth.

It is like choosing between a rock and a hard place. The only two options at your disposal if you run into this problem are — to run away from it or employ template magic. Boost has done the template magic rather very well, but I feel the library is too cryptic. The solution I am suggesting is far from ideal, but I hope it provides a feasible alternative.