【问题标题】:Macro for nested i, j loop嵌套 i, j 循环的宏
【发布时间】:2020-11-17 11:26:07
【问题描述】:

如何编写一个可以使用的宏,如下:

FOR(n)
    FOR(j, n)
        //do stuff

并扩展为有效的嵌套 C++ for 循环,其中:

  • FOR(n) 将使用一个名为 i 的循环变量(默认情况)并且不变量小于 (<) n
  • FOR(j, n) 将使用一个循环变量命名为第一个参数 (j) 并且不变量小于 (<) n?

我看到一个有竞争力的程序员用 C++ 编写这种宏,但我自己一直没能写出这样的宏。

【问题讨论】:

  • 你尝试了吗?使用你不理解的其他宏比使用宏更糟糕;)
  • 欢迎来到 Stackoverflow。请使用tour 并阅读How to ask?。它将为您赢得第一个徽章
  • MACRO 没有“重载”,但有可变参数 MACRO,并且可以计算参数并分派给其他 MACRO。
  • 我读到你知道这是一种不好的做法,但我仍然想强调,如果你是某种编程语言的初学者,你应该避免看任何与竞争相关的东西,你只是学习/发现以后通常很难改掉的坏习惯。
  • @idclev463035818:for range 似乎比std::for_each 更自然(我不记得经常使用)。

标签: c++ macros


【解决方案1】:

我知道这样做是不好的做法 [...]

让我们首先再次强调这一点:是的,这是可怕的做法


现在,看起来像宏重载的东西实际上是宏调度,如在 e.g.以下问答:

使用来自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 */
}

请注意,宏化 for 循环的 (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";
    }
}

【讨论】:

  • #define FOR_1(n) FOR_2(i, n) 为了简洁 ;-)
  • {} 也可以在使用FOR 时添加,就像普通的for 一样
  • @Jarod42 啊,是的,这些是更好/更清晰的 arg 名称(更新为 IN,以及关于范围界定的说明)。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 2014-11-25
相关资源
最近更新 更多