嵌套 i, j 循环的宏
Macro for nested i, j loop
如何编写一个宏,可以如下使用:
FOR(n)
FOR(j, n)
//do stuff
并扩展为有效的嵌套 C++ for 循环,其中:
FOR(n)
将使用一个名为 i
的循环变量(默认情况)并且不变量小于 (<
) n
,
FOR(j, n)
将使用一个循环变量命名为第一个参数 (j
) 并且不变量小于 (<
) n
?
我看到一个竞争性程序员编程C++使用的这种宏,但我自己写不出这样的宏。
I'm aware it's bad practice to do things like this [...]
让我们再次强调这一点:是的,这是可怕的做法。
现在,看起来像宏重载的实际上是宏分派,如详细介绍。以下问答:
- Can macros be overloaded by number of arguments?
使用来自 the accepted answer 的库代码:
#define CAT( A, B ) A ## B
#define SELECT( NAME, NUM ) CAT( NAME ## _, NUM )
#define GET_COUNT( _1, _2, _3, _4, _5, _6 /* ad nauseam */, COUNT, ... ) COUNT
#define VA_SIZE( ... ) GET_COUNT( __VA_ARGS__, 6, 5, 4, 3, 2, 1 )
#define VA_SELECT( NAME, ... ) SELECT( NAME, VA_SIZE(__VA_ARGS__) )(__VA_ARGS__)
我们可以定义各种 FOR_N
重载,例如如下:
// Dispatch macro.
#define FOR( ... ) VA_SELECT( FOR, __VA_ARGS__ )
// Dispatch for 1 or 2 macro arguments for dispatch function.
#define FOR_1(N) for(int i = 0; i < N; ++i)
#define FOR_2(I, N) for(int I = 0; I < N; ++I)
使用如下:
int main() {
int n = 3;
FOR(n)
FOR(j, n)
std::cout << i << " " << j << "\n";
/* 0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2 */
}
请注意,宏循环的 (Pascalesque) 范围可能仅限于一行,因为它们扩展到
for(int i = 0; i < n; ++i)
for(int j = 0; j < n; ++j)
std::cout << i << " " << j << "\n";
而不是
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
std::cout << i << " " << j << "\n";
}
}
要实现后者,您需要类似地显式添加块作用域:
FOR(n) {
FOR(j, n) {
std::cout << i << " " << j << "\n";
}
}
如何编写一个宏,可以如下使用:
FOR(n)
FOR(j, n)
//do stuff
并扩展为有效的嵌套 C++ for 循环,其中:
FOR(n)
将使用一个名为i
的循环变量(默认情况)并且不变量小于 (<
)n
,FOR(j, n)
将使用一个循环变量命名为第一个参数 (j
) 并且不变量小于 (<
)n
?
我看到一个竞争性程序员编程C++使用的这种宏,但我自己写不出这样的宏。
I'm aware it's bad practice to do things like this [...]
让我们再次强调这一点:是的,这是可怕的做法。
现在,看起来像宏重载的实际上是宏分派,如详细介绍。以下问答:
- Can macros be overloaded by number of arguments?
使用来自 the accepted answer 的库代码:
#define CAT( A, B ) A ## B #define SELECT( NAME, NUM ) CAT( NAME ## _, NUM ) #define GET_COUNT( _1, _2, _3, _4, _5, _6 /* ad nauseam */, COUNT, ... ) COUNT #define VA_SIZE( ... ) GET_COUNT( __VA_ARGS__, 6, 5, 4, 3, 2, 1 ) #define VA_SELECT( NAME, ... ) SELECT( NAME, VA_SIZE(__VA_ARGS__) )(__VA_ARGS__)
我们可以定义各种 FOR_N
重载,例如如下:
// Dispatch macro.
#define FOR( ... ) VA_SELECT( FOR, __VA_ARGS__ )
// Dispatch for 1 or 2 macro arguments for dispatch function.
#define FOR_1(N) for(int i = 0; i < N; ++i)
#define FOR_2(I, N) for(int I = 0; I < N; ++I)
使用如下:
int main() {
int n = 3;
FOR(n)
FOR(j, n)
std::cout << i << " " << j << "\n";
/* 0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2 */
}
请注意,宏循环的 (Pascalesque) 范围可能仅限于一行,因为它们扩展到
for(int i = 0; i < n; ++i)
for(int j = 0; j < n; ++j)
std::cout << i << " " << j << "\n";
而不是
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
std::cout << i << " " << j << "\n";
}
}
要实现后者,您需要类似地显式添加块作用域:
FOR(n) {
FOR(j, n) {
std::cout << i << " " << j << "\n";
}
}