I'm working with two macros in C and would like to combine them to initialize an array of strings. Here are the macros in question:
#define FOREACH_T(ACTION) \
ACTION("T1", 1) \
ACTION("T2", 2) \
ACTION("T3", 3)
#define FOREACH_K(ACTION) \
ACTION("K1", 17) \
ACTION("K2", 20) \
ACTION("K3", 23)
My goal is to combine these macros in such a way as to obtain a value array such that, for example, the element at index [1 + 17]
is "T1_K1"
.
I'm a bit at a loss as to how to combine these macros to achieve the desired result. I'd like to get something like this:
const char* value[] = { [1 + 17] = "T1_K1", [1 + 20] = "T1_K2", [1 + 23] = "T1_K3",
[2 + 17] = "T2_K1", [2 + 20] = "T2_K2", [2 + 23] = "T2_K3",
[3 + 17] = "T3_K1", [3 + 20] = "T3_K2", [3 + 23] = "T3_K3"};
};
If you can change the list macros, then it's simple. Doing it without changing the macros should also be possible, but harder.
#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,)
};
Note that this emits warning: initializer overrides prior initialization of this subobject
, because e.g. 1+18 == 2+17
, and so on.
Here's the same thing without changing the macro. This uses macro_sequence_for
, a library I made for writing preprocessor loops that would otherwise be too tricky.
Note that with this, you might as well simplify the macros to lists like ("T1",1)("T2",2)("T3",3)
, no need to accept another macro as the argument. This solution ends up converting the lists to this form first.
#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))
};