CygnusX1
CygnusX1

Reputation: 21779

Capture a name in C macro

The following iterator macro is given to me (cannot change)

#define ITERATE(MACRO) \
    MACRO(v1) \
    MACRO(v2) \
    MACRO(v3) \
    MACRO(v4)

The idea behind this is that I can now define my own one-argument macro and pass it into the iterator to expand for v1, v2, v3, v4. For example:

#define MYSTUFF(X) doSth(X);
ITERATE(MYSTUFF)

will expand to

doSth(v1); doSth(v2); doSth(v3); doSth(v4);

My current problem is that I want to invoke ITERATE within another macro which would like to pass an extra argument into MYSTUFF beyond one provided by the ITERATE.

To achieve that I was hoping that I could capture the extra parameter name with the following construct:

#define PARTIAL(T) FULL(UUU,T)
#define FULL(U,V) doSth(U,V)
#define START(UUU) ITERATE(PARTIAL)
START(bla)

I was hoping that when ITERATE(PARTIAL) is expanded to:

FULL(UUU,v1) FULL(UUU,v2) FULL(UUU,v3) FULL(UUU,v4)

I will actually capture the UUU parameter of START and it will be replaced by bla. Unfortunately that is not the case (at least in gcc).

Upvotes: 2

Views: 541

Answers (2)

Kos
Kos

Reputation: 72241

Your problem, simplified, looks like this:

#define FOO UUU
#define START(UUU) FOO
START(5)

Here's what happens:

  • macro START is encountered in line START(5)
    • START is a function-like macro, so it becomes expanded with argument UUU=5):
      • stage 1 (argument expansion): macro arguments are macro-expanded
        Nothing happens, 5 is not a macro.
        Body: FOO
      • stage 2 (argument prescan): macro arguments are substituted into the macro body.
        Nothing happens, UUU is not in the body.
        Body: FOO
      • stage 3 (expansion): the body is macro-expanded again
        FOO gets expanded into UUU, which is not a macro.
        Body: UUU

I can't think of any clever way to expand FOO inside the body before the argument prescan happens. I don't think it's possible to do what you want directly.

Go with @Hasturkun's workaround and make UUU a macro, not a parameter.

Upvotes: 2

Hasturkun
Hasturkun

Reputation: 36402

You can't do it this way. Your START() macro basically takes a single argument, which it then discards.

What you can do is define UUU where you need it, eg.

#define PARTIAL(T) FULL(UUU,T)
#define FULL(U,V) doSth(U,V)
#define START() ITERATE(PARTIAL)

// ...

#define UUU blah

START()

#undef UUU

Upvotes: 2

Related Questions