プリプロセッサでFOR_EACHを実現する
[プリプロセッサ, 再帰]などで検索して来られる方が居ますがCプリプロセッサで再帰は出来ません。 プリプロセッサメタプログラミングにおける要素の走査は、再帰っぽく見えるだけで実際にはただの連番マクロを用いた展開によって実装されています。
少し実用的な可変長引数を順番に展開する例を掲載しておきます。
#define CAT_I(x, y) x ## y #define CAT(x, y) CAT_I(x, y) #define INC0 1 #define INC1 2 #define INC2 3 #define INC3 4 #define INC4 5 #define INC5 6 #define INC6 7 #define INC7 8 #define INC8 9 #define INC(i) CAT(INC, i) #define EMPTY(...) #define DEF_COMMA0 _,1 EMPTY #define COMMA0() ,0 #define IS_EMPTY_III(f, s) s #define IS_EMPTY_II(t) IS_EMPTY_III t #define IS_EMPTY_I(x) IS_EMPTY_II((DEF_ ## x())) #define IS_EMPTY(x, ...) IS_EMPTY_I(x COMMA0) #define IF_0(x, y) y #define IF_1(x, y) x #define IF(cond, x, y) CAT(IF_, cond)(x, y) #define FOR_EACH_I9(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I8(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I7(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I6(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I5(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I4(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I3(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I2(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I1(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I0(i, F, x, ...) F(x) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH_I(i, F, ...) IF(IS_EMPTY(__VA_ARGS__), EMPTY, CAT(FOR_EACH_I, i))(INC(i), F, __VA_ARGS__) #define FOR_EACH(F, ...) FOR_EACH_I(0, F, __VA_ARGS__) #define HELLO(x) Hello, x! FOR_EACH(HELLO, a, b, c, d, e, f, g)
Output:
Hello, a! Hello, b! Hello, c! Hello, d! Hello, e! Hello, f! Hello, g!