PrevUpHomeNext

Metaprogramming in C++

Template Metaprogramming

C++ templates, of course, provide the language's support for generic programming. These templates can also be used for template metaprogramming. In other words, you can write a C++ metaprogram in C++.

This is clever, cool, and – in the right hands – can even be useful.

I'd be out of my depth even trying to discuss C++ template metaprogramming. Fortunately, there's a growing body of literature and example libraries covering the subject in some depth.

Preprocessor Metaprogramming

As mentioned in passing, C++ has a sophisticated templating facility which (amongst other things) makes metaprogramming possible without needing to step outside the language.

C++ also inherits the C preprocessor: a rather unsophisticated facility, but one which is equally ready for use by metaprogrammers. In fact, careful use of this preprocessor can allow you to create generic C algorithms and simulate lambda functions.

For example:


#define ALL_ITEMS_IN_LIST(T, first, item, ...) \
do  {                                     \
    T * item = first;                     \
    while (item != NULL) {                \
        __VA_ARGS__;                      \
        item = item->next;                \
    }                                     \
} while(0)

#define ALL_FISH_IN_SEA(first_fish, ...) \
        ALL_ITEMS_IN_LIST(Fish, first_fish, fish, __VA_ARGS__)

The first macro, ALL_ITEMS_IN_LIST, iterates through items in a linked list and optionally performs some action on each of them. It requires that list nodes are connected by a next pointer called next. The second macro, ALL_FISH_IN_SEA, specialises the first: the node type is set to Fish * and the list node iterator is called fish instead of item.

Here's an example of how we might use it:


/**
 * @brief Find Nemos
 * @param fishes Linked list of fish
 * @returns The number of fish in the list called Nemo
 */ 
int findNemo(Fish * fishes) 
{
    int count;
     
    ALL_FISH_IN_SEA(fishes,
        if (!strcmp(fish->name, "Nemo")) {
            printf("Found one!\n");
            ++count;
        }
        );
     
    return count;
}

Note how simple it is to plug a code snippet into our generic looping construct. I have used one of C99's variadic macros to do this (these are not yet part of standard C++, but some compilers may support them).

I hesitate to recommend using the preprocessor in this way for all the usual reasons. That said:

One final point: the inline keyword (intentionally) does not require the compiler to inline code. The preprocessor can do nothing but!

Copyright © 2005 Thomas Guest

PrevUpHomeNext