switch(true) with dynamic cases in coldfusion? - coldfusion

To avoid nested if-statements and to improve readability, I wanted to create a
switch(true){ ... } statement in Coldfusion. I used this often in php, but when I try this in Coldfusion, I get the following error at initialization:
Template error
This expression must have a constant value.
This happens when a switch case uses a variable in its condition, like:
//this example throws the error
switch(true){
case foo == 1:
writeOutput('foo is 1');
break;
}
Using a switch(true){ ... } statement with constant values (as the error explains) does work:
//this example doesn't throw the error
switch(true){
case 1 == 1:
writeOutput('1 is 1');
break;
}
Is there any way to get the first statement to work in Coldfusion? Maybe with an evaluation of the variable or some trick, or is this a definite no go in Coldfusion?

In short: no. The case value needs to be something that can be compiled to a constant value. 1==1 can be, as it's just true. foo == 1 cannot be, as foo is only available at runtime.
basically what you're describing is an if / else if / else construct anyhow, so just use one of those.

As Adam and Leigh pointed out, the case values need to be some constant. I'm not sure what your actual use case is but you can do something like this:
switch(foo){
case 1:
writeOutput('foo is 1');
break;
case 2:
writeOutput('foo is 2');
break;
case 3:
writeOutput('foo is 3');
break;
case 4:
case 5:
case 6:
writeOutput('foo is 4 or 5 or 6');
break;
default:
writeOutput("I do not have a case to handle this value: #foo#");
}

As an update on this question, I will note that CF2020 (currently in public beta) has added support for dynamic case values.
And yes, it's done with the understanding that some languages don't allow this, for performance reasons. They are opting to allow it, as other languages do, for readability/flexibility reasons, and leaving the developer to take responsibility for making the cost/benefit tradeoff analysis for their use cases.

Related

Execution of default: in switch-case selection statements in C++ [duplicate]

This question already has answers here:
Switch statement: must default be the last case?
(12 answers)
Closed 5 years ago.
My code :-
#include <iostream>
using namespace std;
int main()
{
int b=10;
switch(b)
{
case 40:
cout<<"no";
default:
cout<<"yes";
case 10:
cout<<"done";
}
return 0;
}
I was just experimenting with my code and tried this scenario. I had expected the output to be :-
yesdone
but the output was :-
done
According to me, since the compiler didn't know about the case 10: when it was reading the default: statement, it must also execute the stuff inside it.
My question :-
i) When is the default: case executed by the compiler and hence why is the output coming out to be
done
rather than
yesdone
Thanks for helping.
P.S :- I am using Code::Blocks with GCC compiler.
Your program jumps to the first matching case.
Only if none is found is the default jumped to instead.
[C++14: 6.4.2/5]: When the switch statement is executed, its condition is evaluated and compared with each case constant. If one of the case constants is equal to the value of the condition, control is passed to the statement following the matched case label. If no case constant matches the condition, and if there is a default label, control passes to the statement labeled by the default label. If no case matches and if there is no default then none of the statements in the switch is executed.
Whenever you find yourself thinking of switch as "a kind of if statement", immediately stop.
According to me, since the compiler didn't know about the case 10: when it was reading the default: statement, it must also execute the stuff inside it.
That is just not how C++ works; it is (somewhat) smarter than that.

C++ Multi Switch and Break?

lets say I have a Code like this
switch (something)
{
case 0:
switch (anotherthing)
{
case 0:
break;
case 1:
break;
default:
break;
}
case 1:
case 4:
break;
case 2:
case 3:
break;
default:
break;
}
Now if I use Case 0 and go to switch (anotherthing), and use break there what will be happen? finish switch (anotherthing)? or Finish switch (something) too?
Is this same in other languages too?
A break statement only breaks the closest switch/loop that it is called in.
In your example, the break statements of the inner switch would only break out of the inner switch, execution would return to case 0 of the other switch. And then, since that case 0 does not have a break of its own, execution would fall through to case 1, which also does not have a break, so execution would fall through to case 4, which does have a break to end the outer switch.
This is certainly true in C and C++, anyway. Not necessarily in other languages. For example, Delphi does not fall-through between case blocks. Break can be used to end a case block early, but it is optional, the block is finished when the end of its scope is reached.
The break will only break out of the innermost switch.
The example you provided would be easy to test this behavior with the addition of some print statements or line breaks.
Please see this documentation on the behavior of C++ breaks.

Why should labels in a case statement be constant?

In JavaScript the following statement is valid.
switch(true) {
case a > b:
max = a;
break;
case a < b:
max = b;
break;
default:
max = a;
}
But in the C/C++ programming languages, when I write this statement, the compiler gives me an error showing that case statement must consist of constant values. Sometimes in particular circumstances writing such switch-case statements would be very useful, but C/C++ will not allow me to do so.
Now I am curious to know what is the point behind this to not allowing variable values to be used in case statements?
C++ has evolved from C where switch statements were conceived as a Jump Table (Branch Table). To implement as jump tables, the switch conditions should be constant such that it can easily be translated to a label.
Though the standard never dictates how the switch statements should be implemented but, most importantly, the case labels should be such that it could be evaluated during compile time. In C and C++, the switch statement evaluates the expression and transfers control to one of the many case statement values that evaluates to the value of the conditional expression.
6.4.2 The switch statement [stmt.switch]
The switch statement causes control to be transferred to one of several statements depending on the value of a condition.
This behaviour makes it different from other languages which supports, conditions in case statements.
As for an instance, Javascript describes switch ... case statement as
MDN switch
The switch statement evaluates an expression, matching the expression's value to a case clause, and executes statements associated with that case.
So you are actually trying to compare two different construct and expecting the behaviour would be the same.
As to answer the point behind this to not allowing variable values to be used in case statements?, that would had made the switch .. case a less efficient construct where for every iteration/instance, the case labels should be re-evaluated to determine if it matches the conditional expression.
The C (rather than C++) Standard says:
C11: 6.8.4.2 The switch statement (p3)
The expression of each case label shall be an integer constant expression and no two of the case constant expressions in the same switch statement shall have the same value after conversion.[...]
If expressions were allowed in case then there are possibilities that two expressions could have same value.
The C++ (rather than C) Standard says the same:
C++11: 6.4.2 paragraph 2:
[...] No two of the case constants in the same switch shall have the same value after conversion to the promoted type of the switch condition.
The reason that switch/case exists (bearing in mind that if/else exists for everything else) is to provide an analogue for lower-level "jump" syntax, so that you can create fast, static "jump tables" for your code. That reason evaporates if you allow runtime expressions.
Asking why switch does this thing is akin to asking why if does the other thing, and is therefore vacuous.
Just because you can do something doesn't mean that makes sense. In particular, switch is not equivalent to if/else ladders.
if/else is more general than switch which is intended to do "select the thing to do based on the value of the switch expression".
Exercise - what would the following code do?
var a = 5;
var b = 0;
switch(a)
{
case 5: b = 1; break;
case 5: b = 2; break;
case 1: b = 3; break;
}
Is now b equal to 2 or 1? If it does both branches, it doesn't do "select one thing to do", if it does one but not the other, it's arbitrary decision.
Restricting the case values to be constant expressions allows compiler to issue error on this code. If the values could be different based on the value at runtime, the compiler couldn't be able to verify that two cases have identical values, as a consequence of Halting problem.

How to access the case value withing the case expression in C/C++

When you have some code like this
switch(some_value)
{
case 1: call_template_function_x<1>();break;
case 2: call_template_function_x<2>();break;
case 3: call_template_function_x<3>();break;
// etc
}
Here 'some_value' is known only at run-time and I'm using the switch to convert the run-time value to one of N functions which have a templated constant as input.
Is there any way I can replace the <1> in the templated function call with the value from the case statement, something like
case n: call_template_function_x<case_value_for_n>();break;
No , there is no way to replace the values unless you write the case for all values from 0 to maximum of some value. This is because call_template_function_x<3>() is known at compile time and because of this the compiler knows what code to generate in the exe. Runtime values therefore will not be able to be used by the compiler to generate code.

switch with some code written before labels, is it okay?

I'm wondering if all compilers would silently ignore code before labels in a switch statement, as VS2005 one does.
Here's what I'm after:
#define CASE break; case
So,
switch (i) {
CASE 0: print("0");
CASE 1: print("1");
}
would turn into
switch (i) {
break;
case 0: print("0"); break;
case 1: print("1");
}
From the standard it seems clear that the first "break" (and any other code there if it existed) wouldn't be executed. The standard doesn't deny existence of such code, but I can't be sure about actual compilers.
Yes, this is implied by §6.4.2¶5 (specifically the ignoring part):
When the switch statement is executed, its condition is evaluated and compared with each case constant. If
one of the case constants is equal to the value of the condition, control is passed to the statement following
the matched case label. If no case constant matches the condition, and if there is a default label, control
passes to the statement labeled by the default label. If no case matches and if there is no default then
none of the statements in the switch is executed.
I don't think your macro is a good idea, however.
Personally, I would be "unable" to write such code, as all warnings are turned into errors, and an unreachable code warning is likely... and in fact, a quick test on clang++ outputs such a warning.