1

我使用宏来编写这样的展开循环:(愚蠢的例子)

#define foreach_small_prime(p, instr) {   \
  int p;                                  \
  p = 2; instr;                           \
  p = 3; instr;                           \
  p = 5; instr;                           \
  p = 7; instr;                           \
}

foreach_small_prime(pp, cout << pp);

int sum = 0;
foreach_small_prime(pp, {
  sum += pp;
  if (sum >= 10) cout << sum << endl;
});

但在某些情况下,我可能会使用 for 构造:

#define foreach_small_even(ii) for(int ii = 0; ii < 20; ii += 2)

int sum = 0;
foreach_small_even(pp) {
  sum += pp;
  if (sum >= 10) cout << sum << endl;
}

我喜欢这个宏,因为我可以将变量作为参数传递。

问题:有没有办法像第二个宏一样以类似 for 的语法定义第一个循环?

4

3 回答 3

7

您可以查看 Boost预处理器库。它可以做各种循环的事情。语法不是很好,但我相信它有效。但是,我自己没有使用过它。

于 2009-05-06T11:43:17.570 回答
0

您是否有充分的理由避免使用迭代器对象?你必须考虑你的第一个宏粘贴 4x 你的 instr 代码......

否则,一个简单的:

#define foreach_smallprime(ii) for(int ii = 0; ii <= 7; ii = next_prime(ii) )

在与next_prime(ii)宏相同的文件中定义。

于 2009-05-06T11:53:58.857 回答
0

问题:有没有办法像第二个宏一样以类似 for 的语法定义第一个循环?

我猜你有一个相对较小的素数工作集,所以为你的素数创建一个查找应该不会太麻烦。如果您需要生成更大的素数列表,我敢肯定 Boost 库中提供了一些编译时模板元编程魔法。如果您要生成更复杂的一系列数字,最好将查找转换为在生成结果时缓存结果的函数。

const int small_primes[MAX_SMALL_PRIMES] = {2, 3, 5, 7, 11, 13};

#define foreach_small_prime(pp) \
  for (int i = 0; i < MAX_SMALL_PRIMES; pp = small_primes[++i])

用作:

void f() {
  int sum = 0;
  int temp = 0;
  foreach_small_prime(temp) {
    sum += temp;
    if (sum >= 10) cout << sum << endl;
  }
}

可能想要折腾查找表和 MAX_SMALL_PRIMES 他们自己的命名空间以避免混乱......并且在宏中使用常用的标识符“i”可能是一个糟糕的选择。我敢肯定还有其他方法可以改进它,但这基本上是您所要求的。

于 2009-05-06T13:13:19.507 回答