提问人:tekknolagi 提问时间:12/14/2021 最后编辑:Jonathan Lefflertekknolagi 更新时间:8/23/2022 访问量:102
组合不同的 arity X-macro
Combine different arity X-macros
问:
我正在为编程语言定义词法分析器。其中一部分涉及包含关键字和标记的表:
#define FOREACH_KEYWORD(V) \
V(And, and) \
V(Else, else) \
V(False, false) \
V(If, if) \
V(Or, or) \
V(True, true)
#define FOREACH_TOKEN(V) \
V(Plus) \
V(Minus) \
V(Times) \
V(Div) \
FOREACH_KEYWORD(V)
这些宏旨在按如下方式使用:
const char *kTokenTypeNames[] = {
#define STR(NAME) #NAME,
FOREACH_TOKEN(STR)
#undef STR
};
// which would ideally expand to
const char *kTokenTypeNames[] = {
"Plus", "Minus", "Times", "Div", "And", "Else", "False", "If", "Or", "True",
};
关键字应包含在令牌列表中。上面的伪代码不起作用,因为两个不同的宏参数具有不同的 arities。我希望任何必须处理标记的宏只需要取 1 个参数,而任何处理关键字的宏都需要取 2 个参数。我宁愿不要让一切都变得多变。我觉得应该可以添加一些插页式宏来使这种组合成为可能,但到目前为止,我还不够聪明,无法做到这一点。V
我想,总的来说:我希望能够获取 arity N 的 X 宏并将其简化为一些 M,其中 M 小于 N。
我怎样才能做到这一点?
答:
4赞
Lundin
12/14/2021
#1
我不确定为什么你认为这两个列表应该是两个而不是一个,当一个列表包含另一个列表时。要么列出一个清单,要么列出两个单独的清单。
如果您创建两个单独的列表并删除列表中的 delete,那么您可以简单地进行两个单独的宏调用:FOREACH_KEYWORD(V)
FOREACH_TOKEN
const char *kTokenTypeNames[] = {
#define STR1(NAME) #NAME,
#define STR2(NAME, dummy) #NAME,
FOREACH_TOKEN1(STR1)
FOREACH_KEYWORD(STR2)
};
2赞
H Walters
12/14/2021
#2
鉴于您的规格,我认为这就是您要找的。
#define AB_TO_A(A,B) (A)
#define EVAL(...) __VA_ARGS__
#define FOREACH_KEYWORD(V) \
V(And, and) \
V(Else, else) \
V(False, false) \
V(If, if) \
V(Or, or) \
V(True, true)
#define FOREACH_TOKEN(V) \
V(Plus) \
V(Minus) \
V(Times) \
V(Div) \
EVAL(FOREACH_KEYWORD(V AB_TO_A))
const char *kTokenTypeNames[] = {
#define STR(NAME) #NAME,
FOREACH_TOKEN(STR)
#undef STR
};
Coliru 演示在这里。
评论
V
V
#define STR(NAME, ...) #NAME,
FOREACH_KEYWORD
FOREACH_TOKEN