I would like to have a group of variable number of arguments passed into a macro. I have following macros which is incorrect:
#define M_NARGS(...) M_NARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define M_NARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
#define M_CONC(A, B) M_CONC_(A, B)
#define M_CONC_(A, B) A##B
#define M_ID(...) __VA_ARGS__
#define M_LEFT(L, R) L
#define M_RIGHT(L, R) R
#define M_FOR_EACH(ACTN, ...) M_CONC(M_FOR_EACH_, M_NARGS(__VA_ARGS__)) (ACTN, __VA_ARGS__)
#define M_FOR_EACH_0(ACTN, E) E
#define M_FOR_EACH_1(ACTN, E) ACTN(E)
#define M_FOR_EACH_2(ACTN, E, ...) ACTN(E) M_FOR_EACH_1(ACTN, __VA_ARGS__)
#define M_FOR_EACH_3(ACTN, E, ...) ACTN(E) M_FOR_EACH_2(ACTN, __VA_ARGS__)
#define M_FOR_EACH_4(ACTN, E, ...) ACTN(E) M_FOR_EACH_3(ACTN, __VA_ARGS__)
#define M_FOR_EACH_5(ACTN, E, ...) ACTN(E) M_FOR_EACH_4(ACTN, __VA_ARGS__)
#define FRUITS (apple, banana, cherry)
#define ANIMALS (dog, monkey)
#define ZOO_BLOCK(NAME, FRTS, ANMLS) struct NAME##Block { \
M_FOR_EACH(DEFINE_FRUITS, FRTS) \ // Wrong, see my question below
M_FOR_EACH(DEFINE_ANIMAL, ANMLS) \ // Wrong
}
#define DEFINE_FRUITS(F) Fruit F;
#define DEFINE_ANIMALS(F) Animal F;
ZOO_BLOCK(MyZoo, FRUITS, ANIMALS);
By M_FOR_EACH(DEFINE_FRUITS, FRTS)
, I would like to do M_FOR_EACH(DEFINE_FRUITS, __VA_ARGS__)
actually and __VA_ARGS__
are all from FRUITS (i.e. apple, banana, cherry). How can I change my macros to do this?
I'm not sure whether this is what you are looking for, but the parenthesised fruit and animal groups are not resolved. You can "flatten" them with your M_ID
macro, e.g.:
#define M_ID(...) __VA_ARGS__
#define FRUITS M_ID(apple, banana, cherry)
#define ANIMALS M_ID(dog, monkey)
#define ZOO_BLOCK(NAME, FRTS, ANMLS) struct NAME##Block { \
M_FOR_EACH(DEFINE_FRUITS, FRTS) \
M_FOR_EACH(DEFINE_ANIMALS, ANMLS) \
}
#define DEFINE_FRUITS(F) Fruit F;
#define DEFINE_ANIMALS(F) Animal F;
ZOO_BLOCK(MyZoo, FRUITS, ANIMALS);
This, together with correcting a minor typo in DEFINE_ANIMAL/S
yields:
struct MyZooBlock {
Fruit apple;
Fruit banana;
Fruit cherry;
Animal dog;
Animal monkey;
};
If you want to generate structs based on lists I would use higher order macros. This does not require you to have another macro that actually does the loop resolution.
#define FRUITS(V) \
V(apple) \
V(banana) \
V(cherry)
#define ANIMALS(V) \
V(dog) \
V(monkey)
#define VISIT_ANI_STRUCT(A) \
Animal A;
#define VISIT_FRU_STRUCT(F) \
Fruit F;
#define ZOO_BLOCK(NAME, GEN_ANI,GEN_FRU) \
struct NAME ## Block { \
ANIMALS(GEN_ANI) \
FRUITS(GEN_FRU) \
}
ZOO_BLOCK(Zoo, VISIT_ANI_STRUCT, VISIT_FRU_STRUCT);
Will result in:
struct ZooBlock { Animal dog; Animal monkey; Fruit apple; Fruit banana; Fruit cherry; };
Or if you need the other way round
#define ZOO_BLOCK(NAME, A, F) \
struct NAME ## Block { \
A(VISIT_ANI_STRUCT) \
F(VISIT_FRU_STRUCT) \
}
ZOO_BLOCK(Zoo, VISIT_ANI_STRUCT, VISIT_FRU_STRUCT);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With