X 宏中元素的条件定义
想象一下,我有一个 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)
这会生成像 void print_foo() { std::cout << 这样的函数.富";};
用于每个 X_MACRO 元素.到目前为止,一切顺利.
This generates functions like void print_foo() { std::cout << "foo"; };
for each of the X_MACRO elements. So far, so good.
但是,现在,我希望 X 宏元素的列表以预处理器宏为条件.例如,如果定义了 USE_ZIP
,则 zip
元素应该只包含在 X 宏中.当然,我不能在X宏里面放一个#ifdef
,比如:
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
我可以将列表写入两次,一次使用 zip
,一次不使用,基于 USE_ZIP
,如下所示:
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
...但这违反了 DRY,更重要的是,如果您需要有条件地包含其他元素,它会迅速失控,这将需要 USE_*
宏的每个可能组合的列表.
... 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?
推荐答案
做到这一点的一种方法是以 base 样式拆分事物并从超级宏中调用它(我不知道如果它们有特殊名称):
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 :-)
另一个巧妙的技巧是有一个简单的条件宏(比如 USE_ZIP
是 0
还是 1
):
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
那么你可以说:
#define X_MACRO(fn)
fn(foo)
fn(bar)
IF(USE_ZIP, fn(zip))
相关文章