2014-10-27 204 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);