views:

141

answers:

3

I couldn't think of a better way to word the title...

#define X(c) c
#define Y(c) X(c)
#undef X

int main(int argc,char*argv[])
{
    std::cout << Y(5) << std::endl;
    return 0;
}

This causes an error, because X() is not declared in this scope. Is there any way to make Y store a copy of X (aka, force the macro substitution to occur as I define Y) such that it no longer depends upon X existing? Perhaps boost has some preprocessor stuff for this, or maybe there's a simple way. Ideas?

+4  A: 

No, there is no way to do that using a standard preprocessor.

Why do you need to undefine X before it's actually used ?

Benoît
+6  A: 

The C preprocessor does brute-force text replacement; it has no sense of scopes and cannot be used to create a closure in this manner.

Ignacio Vazquez-Abrams
A: 

No, it is not possible.

Having used some preprocessing programming myself I do understand the need though: for example for BOOST_PP_FOR_EACH you are supposed to pass a macro to be invoked at each turn of the loop, and yet this macro is only useful locally and then clutter your table of symbols... potentially causing name clashes.

Since there is no way to undef it without causing the macro invoking it not to work, the general solution is to give the macro a long and unwieldy name, so that you don't run into the risk of reusing this name later on.

Boost has a very useful naming convention in this regard:

PROJECT_PATH_FUNCTION

For example, the very BOOST_PP_FOR_EACH I was talking about can be found by including boost/preprocessor/for_each.hpp.

By explicitly stating the path, you not only help people locate your macro quickly, but you also avoid clashes since within a file you can quickly check that you are not messing up.

Matthieu M.