views:

1014

answers:

3

I use macros to code unrolled loops like this: (silly example)

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

But in some cases I might use for construct:

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

I like this macros because I can pass a variable name as a parameter.

Question: Is there a way to define loop like the first one in a for-like syntax like the second macro?

+4  A: 

You could check out the Boost preprocessor library. It can do all sorts of looping things. The syntax isn't great, but I believe it works. I have not used it myself, however.

Michael Kohne
+1  A: 

Do you have a good reason to avoid using an iterator object? You have to consider your first macro pastes 4x your instr code...

Otherwise, a simple :

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

with next_prime(ii) defined in the same file as the macro.

LeGEC
Next_prime would need to determine a prime from the previous one.Iterator object probably won't be unrolled.
Łukasz Lew
+1  A: 

Question: Is there a way to define loop like the first one in a for-like syntax like the second macro?

I guess you have a relatively small working-set of prime numbers, so creating a look-up for your primes shouldn't be too troublesome. If you need to generate a larger list of primes, I'm sure there is some compile-time template meta-programming magic available in the Boost library. If you have a more complex series of numbers you're generating it might be wise to turn the lookup into a function that caches the results as they are generated.

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])

Used as:

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

Probably want to toss the lookup table and MAX_SMALL_PRIMES theirown namespace to avoid clutter... and using a commonly-used identifier 'i' in the macro is probably a poor choice. I'm sure there are other ways to improve it, but this is fundamentally what you're asking for.

veefu
Ah... after re-rereading your question I think I see what you were going after. You wanted loop-unrolling retained, but with the usage syntax of the second construct.
veefu