2009-05-06 140 views
1

我用宏的代码展开的循环是这样的:(愚蠢的例子)C++循环宏

#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; 
}); 

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

#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; 
} 

我喜欢这个宏,因为我可以通过一个变量作为参数名称

问题:有没有像第二个宏那样的像第一个宏那样定义循环的方法?

+2

快速问题,你发现这个展开实际上提高了性能?如果你没有通过配置来证明它确实如此。你应该考虑编写“明显”的方式,让编译器对你很聪明。 – user83255 2009-05-06 14:08:23

+0

停止滥用宏观系统。正是由于这样的滥用,函数内联才是C++的一个必需特性。 – 2009-05-06 14:39:46

+2

事实上,我做了一个非常详细的分析,包括各种g ++选项的asm输出分析。性能差异很大,主要是由于循环中的条件分支。 – 2009-05-06 15:13:35

回答

7

您可以查看Boost preprocessor库。它可以做各种循环的事情。语法不是很好,但我相信它是有效的。然而,我自己并没有使用它。

0

你有避免使用迭代器对象的好理由吗? 你必须考虑你的第一个宏粘贴你的4倍,原音乐代码...

否则,一个简单的:

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

与在同一个文件中的宏定义next_prime(ii)

0

问题:有没有像第二个宏那样的像第一个宏那样定义循环的方法?

我想你有一个相对较小的素数的工作集,所以创建一个素数查找应该不会太麻烦。如果你需要生成一个更大的素数列表,我肯定在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 theirown命名空间,以避免混乱......并使用常用的标识“i”的宏可能是一个可怜的选择。我相信还有其他方法可以改进它,但这基本上是你要求的。