If course you could generate the if
-else
chain using the preprocessor if you really want to (you probably don't), but if it's only this occurence it's most probably not worth it. I think you should really reconsider the possibility to use an array or offsets into the struct.
You could to some limited extent construct loops in the preprocessor. The limitation is that you can't write proper loops so you will end up in a construct that will end up with a limited amount of iterations. Basically what you do to loop n times is to expand LOOP(n,...)
to LOOP#n(...)
and then define LOOPn# for all possible values of
n`.
So what we would want is something like:
if( 0 ) ; // Note: empty statement
else if( r == 1 ) return o->var1;
else if( r == 2 ) return o->var2;
// etc
The if(0)
is to make each variable be handled textually the same. So we can do the first step to define that:
#define HANDLE_VAR(n) else if( r == n ) return o->var ## n;
this would mean that we write it
if(0) ;
HANDLE_VAR(1)
HANDLE_VAR(2)
// etc
Then we define our loop construct:
#define LOOP(n,M) LOOP ## n(M)
#define LOOP(1) M(1)
#define LOOP(2) M(1) M(2)
// etc
then our construct would be
if( 0 ) ; LOOP(31,HANDLE_VAR)
And finally we would wrap it all into a macro:
#define RETURN_VAR if(0) ; LOOP(31,HANDLE_VAR)
There are other options however. The most normal solution would be to use an array to store the variables.
Another would be to write your own preprocessor that supports proper looping, there are ready template processors (genshi for example) that support that.
A third is to calculate the offset into the struct. The suggested method of doing this is not standard compliant though. What you need to do is to have an array of offsets stored:
int StructName::* var_off[] = {
NULL,
&StructName::var1,
&StructName::var2,
// etc
};
and then use o.*var_off[r]
to access var##r
(after checking that r
is in range of course).