NoirDelire
NoirDelire

Reputation: 49

C/C++ Is it possible to #undef a serial of macro starting by the same patern?

I'm writing a tool using macros to generate enum. When done, I want to undef all those macros, but I don't know all names yet. Somes will comes later in developement. So I want to make a generic undef like...

#undef ENUM_*

Is that possible ? The macros simplified looks like that:

First...

#define ENUM_VALUE(VALUE) VALUE,
#define ENUM_STRING(STRING) #STRING,

#define ENUM_GENERATE(NAME)\
    namespace NAME {\
        enum Enum: int { ENUM_##NAME(ENUM_VALUE) };\
        const char *Names[] = { ENUM_##NAME(ENUM_STRING) };\
    }\

Then for each enum I define...

#define ENUM_MyEnum(VALUE)\
    VALUE(Value1)\
    VALUE(Value2)\
    VALUE(Value3)

ENUM_GENERATE(MyEnum)

It generate a synchronized enum and string table like if I had declared

namespace MyEnum { 
    enum Enum: int { Value1, Value2, Value3 };
    const char *Names[] = { "Value1", "Value2", "Value3" };
}

The only problem is that I end with truck load of macros. Somes I don't know yet, because they will be define later when I new enums will be creted. But all start by ENUM_

Is there a simple way to undef them all ? Thanks

Upvotes: 0

Views: 1160

Answers (1)

Yunnosch
Yunnosch

Reputation: 26763

Here is a detailed proposal for the "base macro" idea from comment:
It leaves some defined macros behind, but guarantees that any use is blocked by a single macro not being defined.
I.e. you undef that single one and all attempts to use one of the macros from the group it represents result in a "undefined" error,
or maybe in some defined expansion, which is however sure to annoy the compiler.

// Infrastructure
#define BASE_BASE(ParWhich) BASED_##ParWhich

// Secondary infrastructure, needed for supporting parameterised macros.
#define BASE_NOPAR(ParWhich) BASE_BASE(ParWhich)
#define BASE_ONEPAR(ParWhich, ParOne) BASE_BASE(ParWhich)(ParOne)

// Potentially many macros being defined in a slightly "get-used-to" manner.
#define BASED_A Hello
#define BASED_B(ParWhat) ParWhat
#define BASED_C(ParWord) ParWord

// Example line, to be expanded by prepro with defined macro BASE_BASE.
BASE_NOPAR(A) BASE_ONEPAR(B,PreProcessor) BASE_NOPAR(B)(World.)


// The one line which should lead to compiler errors for any use of one of the macros.
#undef BASE_BASE

// Same example again.
BASE_NOPAR(A) BASE_ONEPAR(B,PreProcessor) BASE_NOPAR(B)(World.)

// Not necessary, just to make sure and to make readable prepro-output.
#define BASE_BASE(ParIgnore) Compiler, please fail here!

// Same example again.
BASE_NOPAR(A) BASE_ONEPAR(B,PreProcessor) BASE_NOPAR(B)(World.)

Using the parameter-free base macro with a parameter in a following pair braces, as done in the example BASE_NOPAR(C)(World.) should not be done directly in code anywhere; because it would, in my opinion, turn into maintenance nightmare soon. I.e. it should be done in a central "core" place as demonstrated otherwise.
Wouldn't want any code written like that.

Output:

>gcc -E -P BaseMacro.c
Hello PreProcessor World.
BASE_BASE(A) BASE_BASE(B)(PreProcessor) BASE_BASE(B)(World.)
Compiler, please fail here! Compiler, please fail here!(PreProcessor) Compiler, please fail here!(World.) Compiler, please fail here!(World.)

Upvotes: 3

Related Questions