简体   繁体   English

一组可变宏

[英]A group of variadic macros

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 (ie apple, banana, cherry). 通过M_FOR_EACH(DEFINE_FRUITS, FRTS) ,我想实际上做M_FOR_EACH(DEFINE_FRUITS, __VA_ARGS__)__VA_ARGS__都来自FRUITS(即苹果,香蕉,樱桃)。 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, eg: 您可以使用M_ID宏“展平”它们,例如:

#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: 这与纠正DEFINE_ANIMAL/S的小错字一起产生:

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM