2014-10-27 94 views
4

我想将一组可变参数传递给一个宏。我有以下宏这是不正确的:一组可变参数宏

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

通过M_FOR_EACH(DEFINE_FRUITS, FRTS),我愿做M_FOR_EACH(DEFINE_FRUITS, __VA_ARGS__)实际和__VA_ARGS__都是从水果(例如苹果,香蕉,樱桃)。我怎样才能改变我的宏来做到这一点?

+4

如果你真的需要这一点,使用Boost的预处理器库。 – chris 2014-10-27 06:47:25

+0

如果我们不使用boost库会怎么样? – yuefengz 2014-10-27 06:58:28

+0

@Fake他们你在很大程度上重新发明轮子。 – Angew 2014-10-27 07:38:21

回答

4

我不确定这是否是您正在寻找的内容,但括号内的水果和动物群体未得到解决。你可以在“扁平化”他们与你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); 

这与DEFINE_ANIMAL/S产量矫正未成年错字在一起:

struct MyZooBlock { 
    Fruit apple; 
    Fruit banana; 
    Fruit cherry; 
    Animal dog; 
    Animal monkey; 
}; 
+2

您可以通过使用'M_ID'解开'ZOO_BLOCK'中的参数列表,而不是要求将其附加到输入,即'M_FOR_EACH(DEFINE_FRUITS,M_ID FRTS)'来提高抽象。 – Leushenko 2014-10-27 15:52:08

+0

@Leushenko:是的,好点。但是在外部使用'M_ID'宏,您不需要额外的宏来创建实体:'ZOO_BLOCK(MyZoo,M_ID(kiwi,pear),M_ID(cat));',这可能很方便。 – 2014-10-27 16:57:33

4

如果您想根据名单我会生成结构使用更高阶的宏。 这并不要求你有另一个实际做循环解析的宏。

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

会导致:

struct ZooBlock { Animal dog; Animal monkey; Fruit apple; Fruit banana; Fruit cherry; }; 

或者,如果你需要的另一种方式圆

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