I l@ve RuBoard Previous Section Next Section

3.6 Indexed Access

Having access by index to the elements of a typelist would certainly be a desirable feature. It would linearize typelist access, making it easier to manipulate typelists comfortably. Of course, as with all the entities we manipulate in our static world, the index must be a compile-time value.

The declaration of a template for an indexed operation would look like this:



template <class TList, unsigned int index> struct TypeAt;


Let's define the algorithm. Keep in mind that we cannot use mutable, modifiable values.


   TypeAt
   Inputs: Typelist TList, index i
   Output: Inner type Result

   If TList is non-null and i is zero, then Result is the head of TList.
   Else
     If TList is non-null and index i is nonzero, then Result is obtained by applying
       TypeAt to the tail of TList and i-1.
     Else there is an out-of-bound access that translates into a compile-time error.

Here's the incarnation of the TypeAt algorithm:



template <class Head, class Tail>


struct TypeAt<Typelist<Head, Tail>, 0>


{


   typedef Head Result;


};


template <class Head, class Tail, unsigned int i>


struct TypeAt<Typelist<Head, Tail>, i>


{


   typedef typename TypeAt<Tail, i - 1>::Result Result;


};


If you try an out-of-bound access, the compiler will complain that there's no specialization defined for TypeAt<NullType, x>, where x is the amount by which you bypass the list size. This message could be a bit more informative, but it's not bad, either.

Loki (file Typelist.h) also defines a variant of TypeAt, called TypeAtNonStrict. TypeAtNonStrict implements the same functionality as TypeAt, with the difference that an out-of-bound access is more forgiving, yielding a user-chosen default type as the result instead of a compile-time error. The generalized callback implementation described in Chapter 5 uses TypeAt-NonStrict.

Indexed access in typelists takes linear time according to the size of the typelist. For lists of values, this method is inefficient (for this reason, std::list does not define an operator[]). However, in the case of typelists, the time is consumed during compilation, and compile time is in a sense "free."[2]

[2] Actually, this is not quite true for large projects. It is possible, at least in theory, that heavy typelist manipulation could slow down compilation time considerably. Anyway, a program that contains very large typelists is either runtime speed-hungry—in which case you are willing to accept slower compilations—or too coupled, in which case a design review would be in order.

    I l@ve RuBoard Previous Section Next Section