这是一些C ++宏代码,它模拟for循环以消除复制和粘贴的代码。
#define SEMICOLON ;
#define LOL(x) print(x)
#define LOLZ(...) FOR_EACH(LOL, SEMICOLON, ##__VA_ARGS__)
LOLZ("hi", "my", "friend", "!");
// result
print("hi"); print("my"); print("friend"); print("!");
我还可以显示创建此宏的代码(我找到了这个here on Stack Overflow):
#define EXPAND(x) x
#define FOR_EACH_1(what, delimiter, x, ...) what(x)
#define FOR_EACH_2(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_1(what, delimiter, __VA_ARGS__))
#define FOR_EACH_3(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_2(what, delimiter, __VA_ARGS__))
#define FOR_EACH_4(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_3(what, delimiter, __VA_ARGS__))
#define FOR_EACH_5(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_4(what, delimiter, __VA_ARGS__))
#define FOR_EACH_6(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_5(what, delimiter, __VA_ARGS__))
#define FOR_EACH_7(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_6(what, delimiter, __VA_ARGS__))
#define FOR_EACH_8(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_7(what, delimiter, __VA_ARGS__))
#define FOR_EACH_9(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_8(what, delimiter, __VA_ARGS__))
#define FOR_EACH_10(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_9(what, delimiter, __VA_ARGS__))
#define FOR_EACH_11(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_10(what, delimiter, __VA_ARGS__))
#define FOR_EACH_12(what, delimiter, x, ...)\
what(x) delimiter\
EXPAND(FOR_EACH_11(what, delimiter, __VA_ARGS__))
#define FOR_EACH_13(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_12(what, delimiter, __VA_ARGS__))
#define FOR_EACH_14(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_13(what, delimiter, __VA_ARGS__))
#define FOR_EACH_15(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_14(what, delimiter, __VA_ARGS__))
#define FOR_EACH_16(what, delimiter, x, ...)\
what(x) delimiter \
EXPAND(FOR_EACH_15(what, delimiter, __VA_ARGS__))
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) EXPAND(FOR_EACH_ARG_N(__VA_ARGS__))
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
#define FOR_EACH_RSEQ_N() 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define CONCATENATE(x,y) x##y
#define FOR_EACH_(N, what, delimiter, ...) EXPAND(CONCATENATE(FOR_EACH_, N)(what, delimiter, __VA_ARGS__))
#define FOR_EACH(what, delimiter, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, delimiter, __VA_ARGS__)
但我对该函数的两个参数有困难: 我需要在这个宏的一次迭代中使用func(x,y)。 调用宏必须看起来像:
MY_DUAL_FOREACH_LIKE_MACRO(
x1, y1,
x2, y2,
x3, y3
)
// and I expect to get:
func(x1, y1); func(x2, y2); func(x3, y3);
如果我添加" y"靠近" x"在宏的论证我将得到x2 unsed替换调用"什么"参数:
func(x1, y1); func(x2, y2); func(x3, y3); func(, ); func(, ); func(, );
如果您有相关经验,请帮我将此宏重新编码为双参数类型FOR_EACH宏。
答案 0 :(得分:3)
反对我更好的判断,我将回答这个问题(因为它在少数情况下很有用)。我修改了您发布的代码,因此需要两个参数(demo):
#include <iostream>
#define EXPAND(x) x
#define FOR_EACH_2(what, delimiter, x, y) what((x), (y))
#define FOR_EACH_4(what, delimiter, x, y, ...)\
what((x), (y)) delimiter \
EXPAND(FOR_EACH_2(what, delimiter, __VA_ARGS__))
#define FOR_EACH_6(what, delimiter, x, y, ...)\
what((x), (y)) delimiter \
EXPAND(FOR_EACH_4(what, delimiter, __VA_ARGS__))
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) EXPAND(FOR_EACH_ARG_N(__VA_ARGS__))
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, N, ...) N
#define FOR_EACH_RSEQ_N() 6, 5, 4, 3, 2, 1, 0
#define CONCATENATE(x,y) x##y
#define FOR_EACH_(N, what, delimiter, ...) EXPAND(CONCATENATE(FOR_EACH_, N)(what, delimiter, __VA_ARGS__))
#define FOR_EACH(what, delimiter, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, delimiter, __VA_ARGS__)
void foo(int x, float y) {
std::cout << "foo(" << x << ", " << y << ")\n";
}
int main() {
FOR_EACH(foo, ;, 1, 3.14, 2, 1.41, 3, 1.73);
}
输出是:
foo(1, 3.14)
foo(2, 1.41)
foo(3, 1.73)
如果您要拨打foo
次超过3次,则必须添加其他个案,我将其作为练习留给读者。
这可以被清理,并且可能应该被赋予与FOR_EACH
不同的名称(可能类似于FOR_EACH_2
以表示它一次对2个参数进行操作),我将会这样做。留给读者另一个练习。
我把这些东西作为练习留给读者的原因是不鼓励使用这个答案(但不能完全阻止它)。如果你不愿意清理它并根据你的需要量身定做,那就好了。
答案 1 :(得分:2)
通常,我赞成回答上述问题,假设选择解决方案是有原因的。但是我对21世纪C ++中宏的使用有很强烈的看法,所以无论如何我都会将其作为答案发布。
请请, 请 不要以这种方式滥用宏。
你想用一对参数调用一个函数,这是一个完全可以接受,可读,可调试,可维护的解决方案,没有宏:
std::vector<std::pair<double, double>> values = {
{ x1, y1 },
{ x2, y2 },
{ x3, y3 }
};
for(auto& pair : values)
{
f(pair.first, pair.second);
}
如果您愿意,也可以将它们放在一个载体中:
std::vector<double> values = {
x1, y1,
x2, y2,
x3, y3
};
for(int i = 0; i < values.size(); i += 2)
{
f(values[i], values[i + 1]);
}
答案 2 :(得分:1)
如果使用括号将宏参数分组,则每个组将作为一个参数处理。您可以修改宏,以便可以像这样调用它:
MY_DUAL_FOREACH_LIKE_MACRO(
(x1, y1),
(x2, y2),
(x3, y3)
)
然后将宏粘贴func
和(x1, y1)
放在一起。