2009-05-06 138 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」的宏可能是一個可憐的選擇。我相信還有其他方法可以改進它,但這基本上是你要求的。