2009-05-06 2 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

+0

Остановить злоупотребление макросистемой. Именно из-за злоупотреблений, подобных тому, что вложение функций было такой обязательной особенностью C++. –

+2

В общем, я сделал очень подробное профилирование, включая профилирование выходных данных asm с различными параметрами g ++. И разница в производительности большая, в основном из-за условной ветви в цикле. –

ответ

7

Вы можете проверить библиотеку Boost preprocessor. Он может делать всевозможные мелочи. Синтаксис невелик, но я считаю, что он работает. Однако я не использовал его сам.

0

У вас есть веская причина избежать использования объекта итератора? Вы должны рассмотреть ваши первые макро пасты 4x код Instr ...

В противном случае, простой:

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

с next_prime(ii), определенной в том же файле макроса.

+0

Next_prime нужно будет определить начальное число из предыдущего. Объект итератора, вероятно, не будет развернут. –

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 пространство имен, чтобы избежать путаницы ... и с помощью широко используемых идентификатор «я» в макрос, вероятно, плохой выбор. Я уверен, что есть другие способы улучшить его, но это в основном то, о чем вы просите.

+0

Ах ... после повторного пересмотра вашего вопроса, я думаю, что вижу, что вы собираетесь делать. Вы хотели, чтобы циклическая развертка сохранялась, но с синтаксисом использования второй конструкции. – veefu