Is it possible to jump from an unnamed scope?
void MyFunc() {
{
... // Code
if (!head_size) {
goto _common_error; // <- break and continue don't work here
}
... // Code
if (!tail_size) {
goto _common_error; // second time
}
... // Code
}
_common_error:
{
... // Code
}
}
My question is not whether this can be redesigned, but whether there is a trick in c++ that I don't know.
Is there a mechanism in c++ other than goto to jump out of an unnamed scope? break and continue do not work in scopes.
Update1: changed word namespace to scope
Yes, you need to use goto to jump out of a scope.
break can only be used to jump out of a loop or switch.
But you can use a (questionable) trick by using a dummy loop:
void MyFunc() {
do {
... // Code
if (!head_size) {
break;
}
... // Code
if (!tail_size) {
break;
}
... // Code
} while (false);
{
... // Error handling code
}
}
Using macro magic
#define BREAKABLE_SCOPE() for (char __scope = 0; __scope == 0; __scope++)
You can then do
int main()
{
// Will only print "Hello!"
BREAKABLE_SCOPE()
{
printf("Hello!");
break;
printf("Hello again!");
}
return 0;
}
Please note that macros will reduce the readability of your code.
Related
According to ISO C++:
The continue statement shall occur only in an iteration-statement and
causes control to pass to the loop-continuation portion of the smallest
enclosing iteration-statement, that is, to the end of the loop. More
precisely, in each of the statements
while (foo) { do { for(;;){
{ { {
// ... //.... //...
} } }
contin:; contin:; contin:;
} } while (foo); }
a continue not contained in an enclosed iteration statement is
equivalent to goto contin
Based on the last part of the quote, I thought that the following would be allowed:
#include <iostream>
using namespace std;
int main() {
continue;
cout << "Will be jumped" << endl;
contin:
}
I thought this will work as a goto statement, jumping to contin. What did I miss?
This is slight phrasing issue. What the quote means is that in
for (;;) {
{
// ...
}
contin: ;
}
The ... can be anything, including another iteration statement.
for (;;) {
{
while(foo()) {
// ...
continue;
}
}
contin: ;
}
The continue; that is not nested inside another looping construct, is going to be equivalent to goto contin;. But if it is contained, it will of course continue the internal loop, not the outer one.
Bear in mind that contin: ; is used for exposition purposes. It doesn't mean there's a literal C++-level label you can do things with.
i am trying to add a developer mode in my program. since duty of car defers every month,i want give my user permission to change every single variables in my program alike duty lccost yen2taka freight
#include <iostream>
using namespace std;
class A
{
public:
int carbid,duty;
void Input()
{
cout<<"please insert the car price you want to bid for(in yen): ";
cin>>carbid;
cout<<"duty of the car: ";
cin>>duty;
}
int Exportcost()
{
int exportcost;
int servicechrg=10;
int freight=20;
exportcost=servicechrg+freight+carbid;
return exportcost;
}
int Yen2taka()
{
int yen2taka;
int taka2dollarrate=10;
int dollar2yen=1;
yen2taka=((Exportcost())/dollar2yen)*taka2dollarrate;
return yen2taka;
}
int Importcost()
{
int importcost;
int lccost=10;
int cnfcost=20;
importcost=lccost+cnfcost;
return importcost;
}
int Totalcosting()
{
int total;
int myprofit=10; //80000
total=myprofit+Importcost()+Yen2taka();
cout<<total;
return total;
}
void summary()
{
cout<<
}
};
int main()
{
x:
A ob;
ob.Input();
ob.Exportcost();
ob.Yen2taka();
ob.Importcost();
ob.Totalcosting();
int ch;
cout<<"press 1 to see the summery of the costing or 2 to restart costing again"<<endl;
cin>>ch;
switch(ch)
{
case 1:
ob.summary();
break;
case 2:
goto x;
}
}
At first, you should collect these parameters in a separate class:
class Configuration // maybe you find a better name...
{
int m_servicechrg = 10; // default
int m_freight = 20;
// ...
public:
int servicechrg() { return m_servicechrg; }
void servicechrg(int value); { /* check some limits? */ m_servicechrg = value; }
int freight() { return m_freight; }
void freight(int value); { /* check some limits? */ m_freight = value; }
// ...
};
// will allow you to do:
// C c; std::cout << c;
ostream& operator<<(ostream& s, Configuration const& c)
{
// which ever formatting is appropriate...
s << c.servicechrg() << ' ' << c.freight();
return s;
}
The setters could alternatively return bool to indicate invalid values.
Now you can use this class within main:
Configuration c;
A a;
int cost = a.exportCost(c); // you'd have to adjust signatures...
int value;
switch(ch)
{
case 4:
if(stc::cin >> freight) // catches invalid user input!
// one ALWAYS should do, otherwise you might end up in
// your program not working any more
{
c.freight(value);
// or, if you have:
if(!c.freight(value))
{
// some appropriate error message
// (it's better not to output in the setter, you are more flexible this
// way – maybe you want different messages at different occasions?)
}
}
else
{
// appropriate error handling
}
break;
default:
// handling invalid user input
// again, you always should; but stream state is not in error state,
// so you just can print appropriate error message
break;
}
See this answer for how to correctly handle stream errors.
If you wonder about the differences in error handling: First case is met if user enters non-numerical input, such as ss, second case, if input is numerical, but out of valid range (77).
Now if you don't want to pass the configuration as parameter all the time, you could make a global variable from (but careful, there are some dangers with global variables, use them as sparely as possible) or implement the singleton pattern.
Side notes: goto can be a fine tool sometimes, but it is a dangerous one (and the label's name x isn't a good one, prefer a name that clearly shows intention, such as REENTRY_POINT, LOOP_START, ...). If you can get along without unreasonable effort, prefer such variants:
bool isRunning = true;
do
{
// ...
case 2:
isRunning = false;
break;
}
while(isRunning);
Sure, an additional variable, an additional check; unfortunately, you cannot use break to exit a (pseudo-) endless loop (for(;;)) (but don't apply this pattern for nested loops, then it gets more and more unreadabla – and ineffcient: bool isExit = false; for(int i = 0; !isExit && i < n; ++i) { for(j = 0; j < n; ++j) { isExit = true; break; } } – see what I mean?). A variant might be:
for(;;)
{
switch(ch)
case 1:
// ...
//break; <- replace
continue;
case 2:
//
break;
} // end of switch
break; // break the surrounding for(;;) loop
}
But that's not really nice either.
A pretty nice variant allowing to exit the loop in the given case, as there isn't anyhting to do afterwards:
for(;;)
{
switch(ch)
{
case 2:
// maybe yet some cleaning up here
return 0;
default:
// ...
break;
}
}
Drawback: The function's exit point possibly is deeply nested inside the code.
There are yet other tricks to allow this pattern, like packing sub-sections of code in a lambda having a return inside and call that one directly. But that now really starts going beyond the scope...
Finally, if you insist on goto, my variant would rather be:
for(;;)
{
switch(ch)
{
case 2:
// ...
goto LOOP_EXIT;
default:
// ...
break;
}
}
LOOP_EXIT:
return 0; // e. g. main
(void)0; // if there isn't anything to do in the function any more
// (labels require an instruction afterwards!)
There won't be a hidden loop now and it is more obvious what you actually are doing. Currently, not really an issue, but if your code grows, the hidden loop gets more and more difficult to spot.
In such cases, I clearly mark the gotos so that another coder can immediately spot the critical code points:
///////////////////////////////////////////////////
// possibly some comment why applying this pattern
goto SOME_LABEL;
///////////////////////////////////////////////////
One could do the same with deeply nested function exit points (return).
In the following example
void fun() {
if(int i=SOME_VALUE) {
// ...
} else {
// ...
}
}
What is the scope of i? Can we use it inside the if-block? Can we use it inside the else-block?
Edit:
As a follow-up, in this modified example
void fun() {
if(int i=SOME_VALUE) {
// ...
} else if(int j=SOME_OTHER_VALUE){
// ...
} else {
// ...
}
}
Can we access both i and j in the else clause?
Yes, and yes.
A typical use for this is dynamic casting:
if (auto p = dynamic_cast<Derived*>(base_pointer))
{
// p is a Derived*
}
else
{
// not the right dynamic type
}
Another construction I've been finding useful:
if (auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(std::fopen("file.txt", "rb"), std::fclose))
{
// file exists, use fp.get()
}
else
{
// file does not exist
}
And one more:
if (pid_t pid = fork())
{
waitpid(pid, nullptr, 0);
}
else
{
execl("/bin/rm", "/bin/rm", "-rf", "/", static_cast<char*>(nullptr));
}
Yes, you can use the variable declared in the if condition in the else substatement like your example.
However, if you declare i inside the if substatement like this:
if (some_condition) {
int i = 42;
// ...
} else {
std::cout << i; //error
// ...
}
in the else part, the variable i is no longer in scope.
Yes, because the variable is "created" in the outermost scope and only then, evaluated in the if condition. Your code could be rewritten like:
int i = SOME_VALUE;
if(i) {
// ...
} else {
// ...
}
and not like:
if(SOME_VALUE) {
int i = SOME_VALUE;
// ...
} else {
// ...
}
as you may have though.
The second question can be answered the same way.
I have a function that looks like this:
int Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return 0;
}
else {
// do other stuff
}
}
}
I'm wondering if it is common or proper to have a returning function, rather than a void function, for the sole purpose of leaving the function (the value being returned wouldn't do anything in the program except for ending the function). Is this good practice, or is there a better way to end a function?
There is no problem with void functions. If it does not return anything useful, it should be void.
Just make your function void, and simply return?
// vv void return type
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return; // <<<< No return value
}
else {
// do other stuff
}
}
}
You can easily just use return; with no parameter to exit a void function. Your above code would become:
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return;
}
else {
// do other stuff
}
}
}
If there is no useful value for the function to return, it is better not to return a value - because the calling code should check the returned value.
Your code can be doubly simplified:
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return;
}
// do other stuff
}
}
The else is unnecessary; the only way to execute the 'do other stuff' is if something is false.
I have compared gcc assembler output of
do {
// some code
} while (0);
with
do {
// some code
break;
} while (1);
The output is equal, with or without optimization but..
It's always that way?
No experiment can prove theories, they can only show they are wrong
There is a slight difference:
do {
// code
if ( condition )
continue;
// code
break;
} while(1);
Will restart the loop when condition is true, whereas in the } while(0); version, the continue will be equivalent to break.
If no continue is present, then they should produce exactly the same code.
The forms are not equivalent. This is an infinite loop:
do {
continue;
break;
} while (1);
This isn't:
do {
continue;
} while (0);
Edit: Upon reading various comments on the matter, I will admit that this answer is wrong. Sorry.
Instead of:
do{
//some code
}while(0);
or:
do{
//some code
break;
}while(1);
I would just use:
//some code
I'm not 100% sure if you can do this in c++, but if you want to limit the scope of variables, and that is why you are doing this, just use curly braces by themselves:
{
// Some Code
}
Markus' comment pointed me to this answer: the difference is when using continue keyword.
In this case:
int _tmain(int argc, _TCHAR* argv[])
{
int i = 0;
do {
++i;
_tprintf(_T("Iteration %d\n"), i);
if (i < 30) continue;
} while(0);
return 0;
}
you get only one iteration, while in this case:
int _tmain(int argc, _TCHAR* argv[])
{
int i = 0;
do {
++i;
_tprintf(_T("Iteration %d\n"), i);
if (i < 30) continue;
break;
} while(1);
return 0;
}
you get 30 iterations. Tested under VS2008.
The do while clauses are logically equivalent. If they are translated to the same byte code depends on the compiler at hand. I guess that most modern compilers will treat them equally.
EDIT based on your comment that you're using a while with breaks in order to be able to break out of the 'loop' when certain conditions have been met.
If this is what you're trying to accomplish:
do
{
// processing step 1
if( some_condition )
break;
// processing step 2
if( some_condition )
break;
// etcetera..
} while(0)
...then just break the code you have in your while loop out to a stand-alone function with multiple returns:
void processing()
{
// processing step 1
if( some_condition )
return;
// processing step 2
if( some_condition )
return;
// etcetera..
}
int main()
{
// ...
processing();
return 0;
}