Вопрос
Я использую макросы для кодирования развернутых циклов следующим образом: (глупый пример)
#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;
}
Мне нравятся эти макросы, потому что я могу передать переменную name в качестве параметра.
Вопрос: есть ли способ определить цикл, подобный первому, в синтаксисе for-like, подобном второму макросу?
Решение
Вы можете проверить библиотеку препроцессора Boost. Это может делать все виды зацикливания вещей. Синтаксис не очень хороший, но я считаю, что он работает. Я не использовал это сам, однако.
Другие советы
У вас есть веская причина избегать использования объекта итератора? Вы должны учитывать, что ваши первые макросы вставляются в 4 раза по вашему коду INSTR ...
В противном случае просто:
#define foreach_smallprime(ii) for(int ii = 0; ii <= 7; ii = next_prime(ii) )
с next_prime (ii)
, определенным в том же файле, что и макрос.
Вопрос: есть ли способ определить цикл, подобный первому, в синтаксисе for-like, подобном второму макросу?
Я полагаю, у вас относительно небольшой рабочий набор простых чисел, поэтому создание поиска для простых чисел не должно быть слишком хлопотным. Если вам нужно сгенерировать больший список простых чисел, я уверен, что в библиотеке 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' в макросе, вероятно, плохой выбор. Я уверен, что есть и другие способы улучшить его, но это в основном то, что вы просите.