Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
836 views
in Technique[技术] by (71.8m points)

c++ - Conditional definition of elements in an X Macro

Imagine I have an X Macro for a list of items defined something like this:

#define X_MACRO(FN) 
  FN(foo) 
  FN(bar) 
  FN(zip)

This works great and I can call it to generate the same code templatized for each element, like:

#define xstr(s) str(s)
#define str(s) #s
#define PRINT_X(E) void print_ ## E () { std::cout << str(E); }; 
X_MACRO(PRINT_X)

This generates functions like void print_foo() { std::cout << "foo"; }; for each of the X_MACRO elements. So far, so good.

Now, however, I want the list of X Macro elements to be conditional on a pre-processor macro. For example the zip element should only be included in the X Macro if USE_ZIP is defined. Of course, I can't put an #ifdef inside the X Macro, like:

#define X_MACRO(FN) 
  FN(foo) 
  FN(bar) 
#ifdef USE_ZIP
  FN(zip)
#endif

I could instead write the list twice, once with zip and once without, based on the USE_ZIP like so:

#ifdef USE_ZIP
#define X_MACRO(FN) 
  FN(foo) 
  FN(bar) 
  FN(zip)
#else
#define X_MACRO(FN) 
  FN(foo) 
  FN(bar)
#endif

... but this violates DRY and more importantly it rapidly spirals out of control if you need to conditionally include other elements, which would require a list for each possible combination of USE_* macros.

How can I do this in a reasonable way?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One way to do this is to split things in a base style and call it from a super macro (I don't know if these have special names):

#define X_MACRO_BASE(fn) 
    fn(foo) 
    fn(bar) 

#if USE_ZIP

#define X_MACRO(fn) 
    X_MACRO_BASE(fn) 
    fn(zip)

#else

#define X_MACRO(fn) 
    X_MACRO_BASE(fn)

#endif

It's not perfect, but it still might be useful :-)


Another neat trick is to have a simple conditional macro (say if USE_ZIP was 0 or 1):

#define IF(cond, foo) IF_IMPL(cond, foo)
#define IF_IMPL(cond, foo) IF_ ## cond (foo)
#define IF_0(foo)
#define IF_1(foo) foo

Then you can say:

#define X_MACRO(fn) 
    fn(foo) 
    fn(bar) 
    IF(USE_ZIP, fn(zip))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...