如果您可以更改列表宏,那么就很简单了.在不更改宏的情况下这样做也应该是可能的,但难度更大.
#define FOREACH_T(ACTION, ...) \
ACTION("T1", 1, __VA_ARGS__) \
ACTION("T2", 2, __VA_ARGS__) \
ACTION("T3", 3, __VA_ARGS__)
#define FOREACH_K(ACTION, ...) \
ACTION("K1", 17, __VA_ARGS__) \
ACTION("K2", 18, __VA_ARGS__) \
ACTION("K3", 19, __VA_ARGS__)
#define FOO(s, x, s2, x2) [x + x2] = s "_" s2,
#define FOO2(s, x, ...) FOREACH_T(FOO, s, x)
const char* value[] = {
FOREACH_K(FOO2,)
};
请注意,这会发出warning: initializer overrides prior initialization of this subobject
,因为例如1+18 == 2+17
等等.
在不更改宏的情况下,也是一样的.它使用macro_sequence_for
,这是我为编写预处理器循环而创建的一个库,否则这些循环会太复杂.
请注意,使用这种方法,您可能会将宏简化为类似于("T1",1)("T2",2)("T3",3)
的列表,而不需要接受另一个宏作为参数.此解决方案最终首先将列表转换为此表单.
run on gcc.godbolt.org
#include <macro_sequence_for.h>
#define FOREACH_T(ACTION) \
ACTION("T1", 1) \
ACTION("T2", 2) \
ACTION("T3", 3)
#define FOREACH_K(ACTION) \
ACTION("K1", 17) \
ACTION("K2", 18) \
ACTION("K3", 19)
#define IDENTITY(...) __VA_ARGS__
#define PARENS(...) (__VA_ARGS__)
#define BODY(n, d, name, value) BODY2(IDENTITY d, name, value)
#define BODY2(...) BODY3(__VA_ARGS__)
#define BODY3(name1, value1, name2, value2) [value1 + value2] = name1 "_" name2,
#define OUTER_BODY(n, d, name, value) SF_FOR_EACH0(BODY, SF_STATE, SF_NULL, (name, value), FOREACH_K(PARENS))
const char *value[] = {
SF_FOR_EACH(OUTER_BODY, SF_NULL, SF_NULL,, FOREACH_T(PARENS))
};