Reputation: 49
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
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