问题
I wanted to use macro functions in switch statements before I realized the statements need to be constant. Example (does not compile):
#define BAND_FIELD1(B) (10 * B + 1)
...
#define BAND_FIELD7(B) (10 * B + 7)
int B = myField % 10;
switch (myField) {
case BAND_FIELD1(B):
variable1[B] = 123;
break;
case BAND_FIELD7(B):
variable7[B] = 321;
break;
...
}
I rather had to use if .. else:
if (myField == BAND_FIELD1(B)
variable1[B] = 123;
else if (myField == BAND_FIELD7(B)
variable7[B] = 321;
Why are the C++ switch statements limited to constant expressions?
回答1:
One of the strengths of C++ is its static checking. The switch
statement is a static control flow construct, whose power lies in the ability to check (statically) whether all cases have been considered, and in being able to group cases sensibly (e.g. fall through common parts).
If you want to check conditions dynamically, you can already do so with a variety of techniques (if
statements, conditional operators, associative arrays, virtual functions, to name a few).
回答2:
Why are the c++ switch statements limited to constant expressions?
Because the check performed by the switch
statements are static. This means that the expressions need to be known at compile time.
In C++11 you can use constexpr
(if the expressions are derivated by other constant expressions) in your favor. For example consider this function (that replaces your #define
):
inline constexpr int BAND_FIELD1(int B) {
return 10 * B + 1;
}
used in the following simplified version of your code:
constexpr int myField = 0;
constexpr int B = myField % 10;
int variable1 = 0;
switch (myField) {
case BAND_FIELD1(B):
variable1 = 123;
break;
// ...
default: break;
}
As you can see, the above code will easily compile.
回答3:
The compiler can generate the fastest possible code for a switch when presented with constants--e.g. jump tables or binary search trees.
When given non-constant values, it can't generate code that's any faster than chained if
-else
statements. Which you already have at your disposal anyway!
回答4:
My answer would be that the C++ switch is a leftover from the C switch, which is a leftover from antique languages like PL/M.
This case uniqueness is just a chance byproduct of a construct that dates back from the 70's, in my opinion.
It does not guarantee in any way that all cases have been covered, especially given the weak typing of C++ enums.
Considering the piles of assembly code C++ routinely generates behind the scene, arguing that C++ switch is limited to constants for performance reasons seems a bit rich to me.
Many other languages support variables and/or non-numeric expressions in switch statements, and I haven't seen many programmers complain about the possible duplicate case values.
回答5:
To help answer the question, consider the following (IF it was legal):
int a=15;
int b=16;
int c=15;
int value = a;
switch (value)
{
case a:
// Value is A
break;
case b:
// value is B
break;
case c:
// value is C
break;
default:
// value is unknown
}
We would never execute the code for C, because A would be executed instead. The purpose of switch is that check a value which has unique, testable values. Its a clean if..else if..else..if..else.
回答6:
Compilers analyze the constant values at compile time to generate optimized lookup tables and decision trees to select a case quickly. For example, if a table can’t be used, the compiler may generate efficient trinary decision trees using sets of 3 cpu instructions: compare to a value to set cpu flags, branch lower to other cases, branch higher to other cases, or fall through to the equal case. Remember that C/C++ is concerned with performance. Maybe a new syntax will be added or compilers will be expanded in the future, but standards advancements try to be incremental and not break code that was already written, or invalidate existing compilers.
来源:https://stackoverflow.com/questions/21321864/why-are-c-switch-statements-limited-to-constant-expressions