Saturday, June 23, 2012

A Macro Interlude

Or... Traversing Macro Pasting Hell

Full disclaimer: This article used to be very different but was also complete tosh. The code I wrote based on its assumptions and misinformation was working fine for days and then broke around 5 minutes after posting the article when I discovered a new use case. This new article addresses that use case and the subsequent solution

Macro pasting

The C preprocessor has a handy (if not essential) operator for pasting 2 tokens together, ##. I use it all over the place in my OOOCode project to generate class and function names, etc using macros. It can be used like this...

Now consider the following...

In this second example I have passed a macro in as an argument to the PASTE macro and as a result it does not get expanded. In order to fix this it is necessary to add a level of indirection...

As an aside, this same problem (and solution) occurs with the quoting operator, #, too.

Variadic macros and swallowing extra commas

Now it gets interesting as the pasting operator can also be used in variadic macros to swallow commas when no arguments are provided...

Handy, yeah? Well sort of. The problem is that this still exhibits the same problems as above when macros are used as arguments...

Macro pasting variadic hell

The above code does not compile as the second macro call does not get expanded. So I tried this...

I'm not sure if this would work in other environments but the C Preprocessor that comes with the OpenTV IDE doesn't swallow the comma in this case.

This gave me a big problem. I can either support macros as arguments or zero length argument lists... but not both :(

Believe me I tried a great many more constructions involving the ## operator and various indirections but to no avail. It just wasn't happening. Eventually (it was quite long time that may even have involved praying as I was a long way into my OOOCode stuff and this was pretty key) I came across a different solution involving detecting empty argument lists. Doing this is not simple and definitely not something I want to get into here, but just know that in the following example the ISEMPTY macro expands to 1 if the argument list supplied is empty or 0 if not...

For the ISEMPTY macro stuff, special thanks have to go to Jens Gustedt and this article:

http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/

2 comments:

  1. Hi Peter,
    I have the impression that you could well profit from integrating P99 into your OO project. It already has:

    - default arguments for functions
    - type generic macros as a replacement for function overloading
    - macro conditional expansion
    - a initialization convention (AKA constructor) that allows for something like P99_NEW(toto, ... arguments)
    - exceptions that throw int's
    - threads

    Jens

    ReplyDelete
  2. Hi Jens,

    You're probably right although i'll likely have to do some porting to get it to work. In particular I can't use unnamed variadic arguments like this:

    #define MYMACRO(...) doSomething(__VA_ARGS__)

    I would have to change such macros to:

    #define MYMACRO(ARGS...) doSomething(ARGS)

    Anyway, nice to hear from you - I really did appreciate the empty argument stuff :)

    ReplyDelete