This yields warning C4715: not all control paths return a value.
int f_no_default(bool true_or_false)
{
switch (true_or_false)
{
case (true) :
return 1;
case (false) :
return 0;
}
}
But this yields warning C4809: switch statement has redundant 'default' label; all possible 'case' labels are given.
int f_with_default(bool true_or_false)
{
switch (true_or_false)
{
case (true) :
return 1;
case (false) :
return 0;
default:
return 0;
}
}
What can I do? (other than turn off treat warnings as errors)
Visual Studio 2013 V12.0
What can I do? (other than turn off treat warnings as errors)
The following code might probably fix it:
int f_no_default(bool true_or_false)
{
switch (true_or_false)
{
case (true) :
return 1;
case (false) :
return 0;
}
return 0; // <<<<<<<<<<<<<<<<<
}
That's a silly warning for the case, but the static analysis capabilities depend on the actual compiler implementation, so do the usefulness of warning messages.
Another option (more compliant with your function name) would be to throw an exception:
int f_no_default(bool true_or_false)
{
switch (true_or_false)
{
case (true) :
return 1;
case (false) :
return 0;
}
throw std::runtime_error("Unecpected value for 'true_or_false'");
}
Related
I need to make foo compile by implementing the macros for it:
int foo(std::string tag)
{
SWITCH_STRING(tag)
{
STRING_CASE(a)
{
return 1;
}
STRING_CASE(b)
{
return 2;
}
STRING_CASE(abc)
{
return 3;
}
STRING_ELSE
{
return -1;
}
}
}
I would like to use the tag parameter in SWITCH_STRING(tag) and compare it to the letter parameter in STRING_CASE(letter), to implement this switch like syntax, I'm stuck for a while and new to macros in c++ could you offer a solution to how to implement the macros please?
#include <iostream>
#include <string>
// Write macros here |
#define SWITCH_STRING(tag)
#define STRING_CASE(letter) letter == tag ? true : false
#define STRING_ELSE
I have to admit: Macros can be fun. We all should know that they should be avoided. Though, as this is an exercise about macros, we can put the discussion whether to use a macro or not aside.
The point of the exercise is that you cannot (directly) switch on a std::string. This answer shows how this limitation can be worked-around. Being required to write exremely verbose repetetive code, the macro is kind of justified. For the sake of completeness I want to add how it can be solved using your original approach, using a series of if instead of the switch.
First, I write the function that does what is asked for without any macro involved:
int foo(std::string tag)
{
std::string& temp = tag;
{
if (temp == "a")
{
return 1;
}
if (temp == "b")
{
return 2;
}
if (temp == "abc")
{
return 3;
}
{
return -1;
}
}
}
It isnt that nice that it uses ifs not else if that should be prefered for mutually exclusive cases. However, as each case returns, the result wont differ (if that isnt the case, you'll have to add some goto vodoo as outlined in the other answer). Having that, it is straightforward to see what macros are needed:
#define SWITCH_STRING(tag) std::string& temp = tag;
#define STRING_CASE(X) if (temp == #X)
#define STRING_ELSE
This kind of answers your question about how to use the parameter of one macro in a second one: You don't. Instead you can use a reference whose name does not depend on the actual name of tag anymore.
Full example
What you might do to switch on string:
constexpr std::size_t myhash(std::string_view) { /* .. */ }
int foo(const std::string& tag)
{
switch (tag)
{
case myhash("a"): { return 1; }
case myhash("b"): { return 2; }
case myhash("abc"): { return 3; }
default: { return -1; }
}
}
That doesn't need MACRO.
If you have collisions with your cases, compilation would fail (same value in switch)
and you will need another hash function.
If you want to prevent collisions (from input string), you might do:
constexpr std::size_t myhash(std::string_view) { /* .. */ }
int foo(const std::string& tag)
{
switch (tag)
{
case myhash("a"): { if (tag != "a") { goto def; } return 1; }
case myhash("b"): { if (tag != "b") { goto def; } return 2; }
case myhash("abc"): { if (tag != "abc") { goto def; } return 3; }
default: { def: return -1; }
}
}
which might indeed be less verbose with MACRO
#define CaseHash(str, c) case myhash(c): if (str != c) { goto def; }
#define DefaultHash default: def
to result to
constexpr std::size_t myhash(std::string_view) { /* .. */ }
int foo(const std::string& tag)
{
switch (tag)
{
CaseHash(tag, "a") { return 1; }
CaseHash(tag, "b") { return 2; }
CaseHash(tag, "abc") { return 3; }
DefaultHash: { return -1; }
}
}
Is there any way to autogenerate cases if necessary (with certain logic described by example) for a switch? Or maybe you have another suggestion. some code is always the same.
int num = 0; // Global variable
.
.
.
switch (num)
{
case 0:
{
//some code
num++;
break;
}
case 1:
{
if (CHECK(1)) // CHECK is macros for comparing
{
//some code
num++;
}
break;
}
case 2:
{
if (CHECK(1) && CHECK(2))
{
//some code
num++;
}
break;
}
case 3:
{
if (CHECK(1) && CHECK(2) && CHECK(3))
{
//some code
num++;
}
break;
}
case 4 ...
... and so on
Unless you're doing something fishy inside CHECK, it should be as easy as a for loop:
for(int i = 1; i <= num; ++i)
if(!CHECK(i))
return;
// some code
++num;
Sure. You can generate whatever code you need, stick it in a file, and then #include the generated file wherever needed in your source file.
Doing that can sometimes be a good idea and sometimes a horrible idea. It all depends on your code/problem/circumstances.
I have proposed using templates in this case.
template <int level>
bool check()
{
return CHECK(level) && check<level - 1>();
}
template <>
bool check<0>() { return true;}
template <int level>
void caseCheck(int& num)
{
if (num == level)
{
if (check<level>())
// some code
num++;
}
else
caseCheck<level - 1>(num);
}
template <>
void caseCheck<0>(int& num)
{
// some code
num++;
}
caseCheck<NUM_CASES>(num);
I am trying to make a function that looks like below. I want to make it iterative, but I am not sure since I need to keep all paths open.
someFunction( parameters)
{
//do stuff
switch( thing )
case: one
if (something true)
{
try { someFunction( different parameters ) } catch(...) { throw }
case: two
//if else with the else being a throw exception.
case: three
// same
case: four
...
default
return some value
I didnt understand very well ur question, but i will try to help!
How to use EXCEPTIONS:
...
try
{
if(b == 0)
throw("A number cannot be devided by zero!\n");
c = a/b
}
catch(string error)
{
cout << "ERROR: "<< error << endl;
}
return c
...
You could use it in a switch statement, after the catch i will return to the case.
switch(c)
{
case 0:
...
try { ... throw();}
catch() { ... error treatment}
...
break;
case 1:
...
}
The following code uses a switch with enum. The main program passes the argument correctly to the function, but the correct switch line is not executed. Can you advise why it is not entering the switch conditions?
enum MyEnum {
Enum1 = 1,
Enum2 = 0x0D
};
bool compute(MyEnum code) {
switch(code) {
Enum1: return true;
Enum2: return false;
};
cout << "why here??" << endl; // this line is getting printed for both inputs
return false;
}
int main() {
cout << "compack=" << compute((MyEnum)1) << endl; // printed "0"
cout << "compack=" << compute((MyEnum)13) << endl; // printed "0"
}
I checked the other questions related to switch and enum (eg 3019153), but cant figure out the bug.
You are missing the case keyword:
switch(code) {
case Enum1: return true;
case Enum2: return false;
};
switch(code)
{
case Enum1: return true;
case Enum2: return false;
};
You forgot to write case
switch(code)
{
case Enum1: return true;
case Enum2: return false;
};
A generic switch is like:
switch(var)
{
case val1:
foo();
break;
case val2:
bar();
break;
default:
error();
};
You forgot case there..
switch(code)
{
case Enum1:
//do something
break;
case Enum2:
//do something
break;
};
Okay, so others have answered that you are missing the case keyword. What hasn't been explained, though, is why the original code compiled. That's because without the case keyword, it was treated as a goto label. In fact, this compiles:
switch (i) {
if (j == 3) {
case 1:;
L1:;
} else {
goto L1;
case 2:;
}
}
Note that the j==3 is actually dead code. It can never be executed. For an actual useful application of this, see Duff's device. By the way, compiling with full warnings enabled would have warned you about an unused goto label, at least with g++ and clang++ (-Wall -Wextra -pedantic).
This question already has answers here:
Case expression not constant
(5 answers)
Closed 5 years ago.
Here is my code:
bool Character::keyPress(char c)
{
switch(c)
{
case up_key:
move(0, -1);
break;
case down_key:
move(0, 1);
break;
case left_key:
move(-1, 0);
break;
case right_key:
move(1,0);
break;
default:
return false;
}
return true;
}
And the compiler complains:
error C2051: case expression not constant
error C2051: case expression not constant
error C2051: case expression not constant
error C2051: case expression not constant
In my header file I have:
protected:
char up_key;
char down_key;
char right_key;
char left_key;
I am using Visual C++ 2008.
As the error message states, the case expressions must be constant. The compiler builds this as a very fast look-up table at compile time and it can't do that if there is a possibility that the values could change as the program runs.
If you do need them to be variable, not constant, your best bet is to use if/else statements instead.
Replace this long clumsy code,
switch(c)
{
case up_key:
move(0, -1);
break;
case down_key:
move(0, 1);
break;
case left_key:
move(-1, 0);
break;
case right_key:
move(1,0);
break;
default:
return false;
}
with something like this:
move( (c==right_key) - (c==left_key) , (c==down_key) - (c==up_key) );
You can litterly replace that 17 lines long of code with that much more neat single line of code.
You can't because the language doesn't work that way. For example, what would happen if up_key, down_key, right_key, and left_key were all equal?
Because the switch statement can take only constants, you know when reading the code that the things you're comparing against are all constants. On the other hand, you would use if statements (or some other structure) to compare against variables:
if (c == up_key) {
move(0, -1);
} else if (c == down_key) {
move(0, 1);
} else ...
This provides a distinct difference in structure which can greatly aid those who come after you in reading your code. Imagine if you had to look up every case label to see whether it was a variable or not?
I believe it's because the compiler generates a jump table, with the values hardcoded in, although I may be wrong. The way the tables are generated just doesn't allow for it.
Since other answers have covered why you are getting an error, here is a way to move in one of the four directions in response to a key press: use lookup tables instead of the conditionals/switches.
Setup portion:
std::map<char,pair<int,int> > moves;
moves[up_key] = make_pair(0, -1);
moves[down_key] = make_pair(0, 1);
moves[left_key] = make_pair(-1, 0);
moves[right_key] = make_pair(1, 0);
The function:
bool Character::keyPress(char c) {
if (moves.count(c)) {
pair<int,int> dir = moves[c];
move(dir.first, dir.second);
return true;
} else {
return false;
}
}
//here is the full functional code snippet which can be compiled and run with most of C++
//compiler/link ...console app was demoed but you can apply the code/logic to win32 app...
//if you have any problem, send me email to Samuel_Ni#yahoo.com
#include <iostream.h>
#include <map>
#include <conio.h>
class CkbdHanler{
private:
map<char,pair<int,int> > moves;
protected:
char up_key;
char down_key;
char right_key;
char left_key;
public:
CkbdHanler(char a,char b,char c,char d):up_key(a),
down_key(b),
right_key(c),
left_key(d)
{
moves[up_key] = make_pair(0, -1);
moves[down_key] = make_pair(0, 1);
moves[left_key] = make_pair(-1, 0);
moves[right_key] = make_pair(1, 0);
}
bool keyPress(char c){
if (moves.count(c)) {
pair<int,int> dir = moves[c];
move(dir.first, dir.second);
return true;
} else return false;
}
void move(int i,int j){
cout<<"(i,j)=("<<i<<","<<j<<")"<<endl;
}
};
int main(int argc, char* argv[])
{
CkbdHanler CmyKbdH('u','d','l','r');
cout << "Hello C++... here is a demo of Map to replace switch-case" << endl;
CmyKbdH.keyPress('d');
cout << endl << "Press any key to continue...";
getch();
return 0;
}