I have a code that compiles on various platforms having different features on or off (each represented by a specific define) and I am scratching my head on how to do the following switch (int) statement that would keep "case (number):" ordered and continuous.
int funcParam;
switch(funcParam)
{
case 0: break;
case 1:break;
#ifdef FEATURE_1
case 2: break;
#endif // FEATURE_1
case 3: break; // <<== problem here: 3 follows 1 if FEATURE_1 is not defined
#ifdef FEATURE_2
case 4: break; <<== problem here: 4 follows 2 if FEATURE_1 is not defined
#endif // FEATURE_2
#ifdef FEATURE_3
case 5: break; <<== problem here: 5 follows 2 or 3 or 4 depending on features
#endif // FEATURE_3
}
Each case block of code is a block of 10 or so lines, I guess this is irrelevant, however the perfect solution to have would be to find a way to emit code like:
case NEXTNUM:
that would expand to a next ordinal number with each expansion of a macro NEXTNUM. Not having an idea on how could it possibly be written.
Please keep in mind that I am using quite old compiler (C 98, may consider C 03).
Thanks, Radek
CodePudding user response:
instead of case 0
, case 1
… and so on, use values from an enum
; these are also compile-time constants, and thus, legal as case
values.
You can insert the same #ifdef
feature checks into the enum
definition, then the enum options are still continuously labeled.
Rule of thumb though:
- you're not making anything prettier that way. Honestly, having a feature enabled or not should probably not change the values functions exchange – that's just ugly and a recipe for debugging disaster. So, I question your motivation!
- a
case
costs nearly nothing. Instead or removing these cases, you should probably think about what the right operation is when that case is triggered. A warning? A system shutdown? - The fact that you're not using an
enum
inswitch
/case
is a really um, bad sign, and you relying on cases still being contiguously numbered is actively worrying. Using magic numerical constants is bad enough style on its own – making them have different meanings on different feature sets screams "architectural mistakes have been made". I'd duly replace all my magic numeric values with entries from an enum. You will be happier afterwards.
Lastly: uff. C 98. C 03 is 20 years old. It's an important bug-fix release that basically broke nothing. You really should not hesitate a second to use it.
CodePudding user response:
Create variables equal 0 and 1 depending on if the feature is enabled. Add these variables to cases after the feature case.
int main() {
int funcParam;
const int add_feature_1 =
#ifdef FEATURE_1
1
#else
0
#endif
;
const int add_feature_2 =
#ifdef FEATURE_2
1
#else
0
#endif
;
const int add_feature_3 =
#ifdef FEATURE_3
1
#else
0
#endif
;
switch(funcParam) {
case 0: break;
case 1: break;
#ifdef FEATURE_1
case 2: break;
#endif
case 2 add_feature_1: break;
#ifdef FEATURE_2
case 3 add_feature_1: break;
#endif // FEATURE_2
#ifdef FEATURE_3
case 3 add_feature_1 add_feature_2: break;
#endif // FEATURE_3
}
}
Consider refactoring your code, so that FEATURE_X has to be defined (which I consider better) and instead define FEATURE_X to number 0 or 1. Then you could:
#define FEATURE_1 0
#define FEATURE_2 1
#define FEATURE_3 0
int main() {
int funcParam;
switch(funcParam) {
case 0: break;
case 1: break;
#if FEATURE_1
case 2: break;
#endif
case 2 FEATURE_1: break;
#if FEATURE_2
case 3 FEATURE_1: break;
#endif // FEATURE_2
#if FEATURE_3
case 3 FEATURE_1 FEATURE_2: break;
#endif // FEATURE_3
}
}
Or similar combinations, you should get the idea.