根据 Dylan 的回答,我编写了一个 python 代码来生成 N 次 for_each 宏。
下面是代码:
from builtins import *
# number of generated for_each cases.
iter_max = 19
# override this with your own!
prefix = "MY_" # define your own macro prefix, which ends with under_score if not empty.
internal_prefix = "internal_"
# CODE ------------------------------------------------------------------------------------------------------
INTERNAL_ = f"{internal_prefix}{prefix}"
fmt_numstr = "{}" # f"{{:0>{max_digit}}}"
EXPAND = f"{INTERNAL_}EXPAND"
FOR_EACH = f"{INTERNAL_}FOR_EACH_"
FOR_EACH_N = f"{FOR_EACH}{fmt_numstr}"
OUT = "#pragma once\n"
OUT += f"#define {EXPAND}(x) x\n"
OUT += f"#define {FOR_EACH_N.format(1)}(what, x, ...) what(x)\n"
for i in range(2, iter_max + 1):
OUT += f"#define {FOR_EACH_N.format(i)}(what, x, ...) " \
f"what(x);" \
f"{EXPAND}({FOR_EACH_N.format(i - 1)}(what, __VA_ARGS__))\n"
FOR_EACH_NARG = f"{INTERNAL_}FOR_EACH_NARG"
FOR_EACH_RSEQ_N = f"{INTERNAL_}FOR_EACH_RSEQ_N"
FOR_EACH_ARG_N = f"{INTERNAL_}FOR_EACH_ARG_N"
OUT += f"#define {FOR_EACH_NARG}(...) {FOR_EACH_NARG}_(__VA_ARGS__, {FOR_EACH_RSEQ_N}())\n"
OUT += f"#define {FOR_EACH_NARG}_(...) {EXPAND}({FOR_EACH_ARG_N}(__VA_ARGS__))\n"
underscore_sequence = ""
inverse_sequence = ""
for i in range(1, iter_max + 1):
underscore_sequence += f"_{i}{',' if i < iter_max else ''}"
for i in range(0, iter_max + 1):
inverse_sequence += f"{fmt_numstr}{',' if i < iter_max else ''} ".format(iter_max - i)
OUT += f"#define {FOR_EACH_ARG_N}({underscore_sequence}, N, ...) N\n"
OUT += f"#define {FOR_EACH_RSEQ_N}() {inverse_sequence}\n"
CONCATENATE = f"{INTERNAL_}CONCATENATE"
OUT += f"#define {CONCATENATE}(x,y) x##y\n"
INTERNAL_FOR_EACH = f"{INTERNAL_}FOR_EACH_"
OUT += f"#define {INTERNAL_FOR_EACH}(N, what, ...) {EXPAND}({CONCATENATE}({FOR_EACH}, N)(what, __VA_ARGS__))\n"
OUT += f"#define {prefix}FOR_EACH(what, ...) {INTERNAL_FOR_EACH}({FOR_EACH_NARG}(__VA_ARGS__), what, __VA_ARGS__)\n"
print(OUT)
执行结果为:
#pragma once
#define internal_MY_EXPAND(x) x
#define internal_MY_FOR_EACH_1(what, x, ...) what(x)
#define internal_MY_FOR_EACH_2(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_1(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_3(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_2(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_4(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_3(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_5(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_4(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_6(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_5(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_7(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_6(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_8(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_7(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_9(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_8(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_10(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_9(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_11(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_10(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_12(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_11(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_13(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_12(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_14(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_13(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_15(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_14(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_16(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_15(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_17(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_16(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_18(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_17(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_19(what, x, ...) what(x);internal_MY_EXPAND(internal_MY_FOR_EACH_18(what, __VA_ARGS__))
#define internal_MY_FOR_EACH_NARG(...) internal_MY_FOR_EACH_NARG_(__VA_ARGS__, internal_MY_FOR_EACH_RSEQ_N())
#define internal_MY_FOR_EACH_NARG_(...) internal_MY_EXPAND(internal_MY_FOR_EACH_ARG_N(__VA_ARGS__))
#define internal_MY_FOR_EACH_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19, N, ...) N
#define internal_MY_FOR_EACH_RSEQ_N() 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define internal_MY_CONCATENATE(x,y) x##y
#define internal_MY_FOR_EACH_(N, what, ...) internal_MY_EXPAND(internal_MY_CONCATENATE(internal_MY_FOR_EACH_, N)(what, __VA_ARGS__))
#define MY_FOR_EACH(what, ...) internal_MY_FOR_EACH_(internal_MY_FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
您可以自定义宏前缀和内部前缀以供自己使用。