I l@ve RuBoard Previous Section Next Section

3.4 Calculating Length

Here's a simple operation. Given a typelist TList, obtain a compile-time constant that evaluates its length. The constant ought to be a compile-time one because typelists are static constructs, so we'd expect all calculations related to typelists to be performed at compile time.

The idea underlying most typelist manipulations is to exploit recursive templates, which are templates that use instantiations of themselves as part of their definition. While doing this, they pass a different template argument list. The recursion obtained this way is stopped with an explicit specialization for a border case.

The code that computes a typelist's length is, again, quite concise:



template <class TList> struct Length;


template <> struct Length<NullType>


{


   enum { value = 0 };


};


template <class T, class U>


struct Length< Typelist<T, U> >


{


   enum { value = 1 + Length<U>::value };


};


This is the C++ way of saying, "The length of a null typelist is 0. The length of any other typelist is 1 plus the length of the tail of that typelist."

The implementation of Length uses partial template specialization (see Chapter 2) to distinguish between a null type and a typelist. The first specialization of Length is totally specialized and matches only NullType. The second, partial, specialization of Length matches any Typelist<T, U>, including compound typelists, that is, those in which U is in turn a Typelist<V, W>.

The second specialization performs the computation by recursion. It defines value as 1 (which counts the head T) plus the length of the tail of the typelist. When the tail becomes NullType, the first definition is matched, the recursion is stopped, and so is the length calculation, which comes back nicely with the result. Suppose, for example, that you want to define a C-style array that collects pointers to std::type_info objects for all signed integrals. Using Length, you can write



std::type_info* intsRtti[Length<SignedIntegrals>::value];


You allocate four elements for intsRtti through a compile-time calculation.[1]

[1] You can also initialize the array without code repetition. Doing this is left as an exercise for the reader.

    I l@ve RuBoard Previous Section Next Section