Meta-programming resources

Hi everyone,
Casey mentions meta-programming on the stream quite often and although I know there are tools available to do that, I was wondering if anyone had experience in implementing one or if you have a good starting point to write my own.

Many Thanks,

Marco
I second this request! While there is no problem to find links to preprocessor tricks and code-generators it would be very interesting to know what Casey means when he speaks of meta-programming.
I think this question was already asked several times and Casey always responds with something like: "It's just C program that spits out code for other C program." and that he doesn't really have any resources to point to.

PS: I wonder if by creating several layers of meta-programming we could get closer to The Variable...

Edited by BlueWolf on
Casey explained in one of Q&A's that his metaprogramming is simply C code that writes C code.
For example, imagine this C++ tempalated mini-stack class:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
template <class T, int MaxSize>
struct Stack
{
    T elements[MaxSize];
    size_t count;

    Stack() : count(0) {}

    void push(T value) { elements[count++] = value; }
    T pop() { return elements[--count]; }
};

And then you want to use this class for different types and sizes:
1
2
3
typedef Stack<int, 100> IntStack;
typedef Stack<float, 500> FoatStack;
typedef Stack<Foo, 30> FooStack;


Let's say you want to do this in C. You can not use templates. But what if you need this stack for many different types - int, float, Foo each with different max size? You won't write all functions for these three types, right? Wwell you could in this case, but imageine you need 50 different types/sizes. So you do metaprogramming:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>

void CreateStack(FILE* Output, char* Name, char* Type, int MaxSize)
{
    fprintf(Output, "struct %s\n", Name);
    fprintf(Output, "{\n");
    fprintf(Output, "    %s Elements[%d];\n", Type, MaxSize);
    fprintf(Output, "    size_t Count;\n");
    fprintf(Output, "};\n");
    fprintf(Output, "void %sPush(%s* Stack, %s Value)\n", Name, Name, Type);
    fprintf(Output, "{\n");
    fprintf(Output, "    Stack->Elements[Stack->Count++] = Value;\n");
    fprintf(Output, "}\n");
    fprintf(Output, "%s %sPop(%s* Stack)\n", Type, Name, Name);
    fprintf(Output, "{\n");
    fprintf(Output, "    return Stack->Elements[--Stack->Count];\n");
    fprintf(Output, "}\n");
    fprintf(Output, "\n");
}

int main()
{
    FILE* Output = fopen("stack.h", "w");
    CreateStack(Output, "IntStack", "int", 100);
    CreateStack(Output, "FloatStack", "float", 500);
    CreateStack(Output, "FooStack", "Foo", 30);
    fclose(Output);
}


Of course this is very silly example, you probably can structure your code without any metaprogramming for these mini-stacks (simple macros?). Better example would be to generate code for serializing and unserializing some data structures to/from file.

Edited by Mārtiņš Možeiko on
If you start googling around, be aware that sometimes people call what (I think) Casey is doing code generation (i.e. you write a program to write another program) and reserve the term "meta-programming" for cases where you are using the facilities of the language itself to generate code automatically. So, in C++, using the preprocessor or template system to generate code would be "meta-programming" and writing a program (regardless of the language used) to output another program is called "code generation." Is that correct terminology? I don't really know or care but it helps when searching.

Here are few links you might find helpful.

The preprocessor is more powerful than most people realize. Here are a few links from basic to black magic (beware that, from what I recall, the last one is using gcc preprocessor extensions so it doesn't all work on MSVC):

Tips and tricks using the preprocessor (part one)
Tips and tricks using the preprocessor (part two)
C Pre-Processor Magic

The template system is the more standard meta-programming facility in modern C++. It gets my vote for the world's worst functional language that people actually use :). I know some books if you are interested but it is pretty main stream so google can tell you everything you need to know.

For code generation, there are a variety of approaches from programs that you run manually when you find you need a new version of something it can generate (like the Stack example above), programs that get hooked into the build system automatically to sophisticated programs that actually parse the C++ that you write and generate additional code for you. Here is a link that discusses the later:

Implementing a code generator with libclang

If you want to go the code generation route, you might want to explore using a template engine or a language like perl that really specializes in text manipulation. You can do it in C but I suspect that Casey has built up a good library over the years that you will not have at the start.

As a quick personal note, a number of years ago I was on a project that involved very sophisticated algorithms and heuristics which really required that domain experts write and tune the initial code themselves. They were experts in their domain but not expert software developer so dealing with pages of template induced error messages was not going to fly. They also needed to do lots of iterations to tune their heuristics so quick builds times were important. To support all this we moved away from templates to code generation and it worked like a charm. The code was much simpler to debug for everyone and build times were much faster. I think boost is a technical tour de force but, in my opinion, it is the wrong way to solve the problem.

Edited by Patrick Lahey on
Here's to hoping Casey can do some metaprogramming for HMH at some point!
Removed...

Edited by Per Erskjäns on Reason: Wrong thread