Question

I need help with macros, please!

Suppose I’ve got the following constants defined

#define foo_tacos_tuesday    1
#define foo_tacos            1
#define foo_nachos_wednesday 2
#define foo_nachos           3

I’d like to write a macro that does the following

#define MyFancyMacro( arg1, arg2 )                     \
     #if ( foo_ ## arg1 ## _ ## arg2 != foo_ ## arg1 ) \
         foo_ ## arg1 ## _ ## arg2, foo_ ## arg1,

So I can set up a mapping table that only maps the mismatching values:

static const int mappingTable[] =
    {
         MyFancyMacro(tacos, tuesday)
         MyFancyMacro(nachos, wednesday)
    };

In the end the mappingTable should just be two ints in length, containing 2 and 3.

Any idea how to do this?

Thanks.

No correct solution

OTHER TIPS

You cannot expand a C preprocessor macro into a preprocessor statement. However, you can use file inclusion to achieve a work-around.

Imagine that you have a header file called m.h that has the following contents:

#ifndef MY_FANCY_HEADER
#define XFOO2(arg1, arg2) foo_ ## arg1 ## _ ## arg2
#define FOO2(arg1, arg2) XFOO2(arg1, arg2)
#define XFOO(arg1) foo_ ## arg1
#define FOO(arg1) XFOO(arg1)
#endif

#define FOO_ARG1_ARG2 FOO2(ARG1, ARG2)
#define FOO_ARG1 FOO(ARG1)

#if FOO_ARG1_ARG2 != FOO_ARG1
    FOO_ARG1_ARG2, FOO_ARG1,
#endif

#undef ARG1
#undef ARG2
#undef FOO_ARG1_ARG2
#undef FOO_ARG1

Then, in your source file, you can do something like this:

static const int mappingTable[] = {
    #define ARG1 tacos
    #define ARG2 tuesday
    #include "m.h"

    #define ARG1 nachos
    #define ARG2 wednesday
    #include "m.h"
};

I admit it is not ideal, but since you cannot expand a macro into a preprocessor statement, I believe this is the only way to do it with the standard C preprocessor.

You can do this with an advanced macro library like Order-PP, although the downside with that is a huge amount of included stuff, potentially slow compile times, and questionable portability*.

A function to do what you ask might look something like this:

#include <order/interpreter.h>

// defining functions is a bit long-winded
#define ORDER_PP_DEF_8fancy ORDER_PP_FN( \
  8fn(8L, 8R, \
      8if( 8equal(8L, 8R), \
           8print(8space), \
           8print(8L 8comma 8R 8comma) ) ) )

// testing this
ORDER_PP (  // (execute Order code)
  8fancy(1, 1)   //should do nothing
)
ORDER_PP (
  8fancy(2, 3)   //should show 2,3,
)

// wrap up in a conventional C macro
#define MyFancyMacro(arg1, arg2) ORDER_PP( \
    8fancy( foo_ ## arg1 ## _ ## arg2, foo_ ## arg1 ) \
)

// test the full version
#define foo_tacos_tuesday    1
#define foo_tacos            1
#define foo_nachos_wednesday 2
#define foo_nachos           3
static const int mappingTable[] =
{
     MyFancyMacro(tacos, tuesday)    //nothing
     MyFancyMacro(nachos, wednesday) //2,3,
};

This is pretty fragile though - it will only work with integers and will barf up an incomprehensible error message if you try to compare something else. Even that requires quite a lot of macro magic behind the scenes to enable something like == (it basically has an extremely large number of preset macros like EQUAL_1_1 returning 1 and EQUAL_1_0 returning 0). A limitation of the Order language also means you need to use a weird format for integers larger than 99.

(if itself is very easy to define as a macro and can be done with only four preprocessor definitions - it's the integer comparison which generates a boolean that's the complex part, since you have to completely reimplement arithmetic itself using nothing but token substitution.)

* Order is standard-compliant, it's most compilers that aren't.


I'd also caution against designing anything with macros that return a trailing comma - that's highly likely to confuse other people (or even you, when you forget), because "syntax in" stops matching up with "syntax out". In fact given that this problem looks like building an array and then filtering values out, why not do that for real at runtime during program initialization?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top