X宏中元素的条件定义

Bee*_*ope 4 c++ macros c-preprocessor

想象一下,我有一个X宏,用于定义如下内容的项目列表:

#define X_MACRO(FN) \
  FN(foo) \
  FN(bar) \
  FN(zip)
Run Code Online (Sandbox Code Playgroud)

这很好用,我可以调用它来生成为每个元素模板化的相同代码,例如:

#define xstr(s) str(s)
#define str(s) #s
#define PRINT_X(E) void print_ ## E () { std::cout << str(E); }; 
X_MACRO(PRINT_X)
Run Code Online (Sandbox Code Playgroud)

这会void print_foo() { std::cout << "foo"; };为每个X_MACRO元素生成类似的函数.到现在为止还挺好.

但是,现在,我希望X宏元素列表以预处理器宏为条件.例如,zip元素应仅包含在X宏中(如果USE_ZIP已定义).当然,我不能把#ifdefX宏放在里面,比如:

#define X_MACRO(FN) \
  FN(foo) \
  FN(bar) \
#ifdef USE_ZIP
  FN(zip)
#endif
Run Code Online (Sandbox Code Playgroud)

我可以改为将列表写两次,一次使用zip,一次不使用,基于USE_ZIP类似:

#ifdef USE_ZIP
#define X_MACRO(FN) \
  FN(foo) \
  FN(bar) \
  FN(zip)
#else
#define X_MACRO(FN) \
  FN(foo) \
  FN(bar)
#endif
Run Code Online (Sandbox Code Playgroud)

...但是这违反了DRY,更重要的是,如果你需要有条件地包含其他元素,它会迅速失控,这需要为每个可能的USE_*宏组合提供一个列表.

我怎样才能以合理的方式做到这一点?

Tra*_*kel 6

一种方法是以基本样式拆分事物并从超级宏调用它(我不知道它们是否具有特殊名称):

#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
Run Code Online (Sandbox Code Playgroud)

它并不完美,但它仍然可能有用:-)


另一个巧妙的技巧是有一个简单的条件宏(比如说USE_ZIP01):

#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
Run Code Online (Sandbox Code Playgroud)

然后你可以说:

#define X_MACRO(fn) \
    fn(foo) \
    fn(bar) \
    IF(USE_ZIP, fn(zip))
Run Code Online (Sandbox Code Playgroud)