0

I'm new to C++. I have the following form of code. I was wondering how I could rewrite this without the use of goto. If I use break in place of it, then I still check the if statement following the loop on every pass through this code even though if I did break I know this condition will fail, so why check it? The only solution I was able to come up with is to make this code a function and replace the goto with a return and remove the if conditional following the loop, leaving just the statements. Would this be a place where goto IS acceptable?

Edit: I should also mention the reason I leave the loop when we find an equal member, is because I don't need to check the remainder of the members in my object cause I already know the one we found is unique to the objects we are iterating, therefore there will never be a match if we continued through the rest of the iterators. So I just exit the loop then.

while (begIt != endIt)
    if ((*begIt).member == someObject.member){
        // Do these statements
        goto someLabel; // then goto someLabel
    }
    ++begIt;
}
if (begIt == endIt){ // We must have not found an equal member
    // So do these statements
}
someLabel: // ...
Wallboy
  • 154
  • 5
  • 14
  • 1
    If you really don't want to use `goto`, you could create a function `somelable()` – yizzlez Mar 22 '14 at 01:33
  • please use neither gotos nor lambdas for this..... I have no idea why everybody is suggesting one of those two.... – example Mar 22 '14 at 01:52
  • @example What's wrong with lambdas? They're perfectly fine. – Rapptz Mar 22 '14 at 02:35
  • @example: Time to explain your viewpoint, because your answer contains arguably the least readable code of any snippet here. – Lightness Races in Orbit Mar 22 '14 at 02:39
  • @Rappatz lambdas are great (and I think your answer is good), but using them as a program-flow mechanism by executing them like `[]{ ... }();` and using return statements inside them only obfuscates the code (and that was the only use of lambdas I saw before commenting). While it might be possible to think of cases where this is an acceptible downside (probably the same cases where gotos are acceptible), this it not one of those. There is no goto or lambda function needed to get this very same behaviour. (see my answer) – example Mar 22 '14 at 02:40
  • @LightnessRacesinOrbit guess we will simply have to disagree. I think my code is _much_ more readable than yours. Imagine someone overlooking those two little symbols `()` before the `;` in your answer... – example Mar 22 '14 at 02:42
  • @Example: Yes, I agree - that's why I did not suggest the lambda (only giving it as an alternative). You'll see my answer says the goto is fine. Admittedly I didn't give a code example of it (because it's already in the question). So, fair enough then, "your answer contains arguably the least readable code of any snippet here, except possibly my lambda example that I don't actually suggest using anyway" :) – Lightness Races in Orbit Mar 22 '14 at 12:49

5 Answers5

10

Use algorithms and lambdas.

auto it = std::find_if(begin, end, [&](const A& a) {
    return a.member == other.member;
});

if(it != end) {
    // found
}
else {
    // not found
}
Rapptz
  • 20,807
  • 5
  • 72
  • 86
  • 1
    It's not really the same because he executes a conditional set of statements per found member, *and* then another behaviour if found. – Puppy Mar 22 '14 at 01:37
  • 3
    @DeadMG: Actually, it is. This is the canonical answer, though it jumps a few conceptual steps from the OP's code. – Lightness Races in Orbit Mar 22 '14 at 01:40
  • I have not learned about lambdas yet, but will look into it. Thanks. I just thought I was missing some simple change in my program to get the exact same result without the use of the goto. – Wallboy Mar 22 '14 at 02:22
4
while (true)
    if (begIt == endIt){ // We must have not found an equal member
        // So do these statements
        break;
    }
    if ((*begIt).member == someObject.member){
        // Do these statements
        break;
    }
    ++begIt;
}

// someLabel: ...

The only solution I would accept in my code. (or seperate function. directly executing a lambda for this is ugly...)

But it is very likely that you are worrying about the wrong things. Inserting a goto will probably not increase performance because the thing that you are intending to "optimize away" is a single conditional (pointer == pointer) which is negligible in 99.9999999% of all programs out there. So even if you are writing high-performance numerical code I would advice you to simple break and check with an if after the loop (I dare you to show me some profiler output to prove me wrong ;) )

example
  • 3,349
  • 1
  • 20
  • 29
  • `Inserting a goto will probably decrease performance because the compiler will disable some optimization routines` Huh? Why's that, then? – Lightness Races in Orbit Mar 22 '14 at 01:52
  • Well I only want to execute the if (begIt == endIt) once OUTSIDE the while loop if we did not find an equal member. Not on every iteration. – Wallboy Mar 22 '14 at 02:00
  • @Wallboy what exactly are you worried about? that is a simple if condition. The loop condition that you have is pretty much equivalent to it. – example Mar 22 '14 at 02:03
  • @LightnessRacesinOrbit Unfortunately I cannot find a credible source at the moment. The best I can do at this late hour is an wikipedia quote `Although these three control structures can all be hand-coded using gotos and ifs, the desire for clarity and efficient optimization led to the introduction and refinement of supporting structures [...]`. While I'm still convinced that the goto will not _improve_ performance, I will still remove the part of my answer about it decreasing performance as long as I have no good source for that. – example Mar 22 '14 at 02:11
  • @Wallboy It seems to me this really is what you want. The `break` statements will exit the loop, so it will not keep iterating after the first equal element and the body of the `if (begIt == endIt)` will only be executed (at most) once. – example Mar 22 '14 at 02:16
  • @example Correct. I have updated my original post to explain why I break out of the loop early when we found the member. And that we execute the If statement after the While loop only once if we did not find the member. – Wallboy Mar 22 '14 at 02:20
  • @Wallboy Yes, I understood how your code works. But you still seem to be worried about how often `(begIt == endIt)` is executed. Please note that the number of evaluated conditions in my code is actually _lower_ than in yours. The `while (begIt != endIt)` will perform one comparison per iteration + you (sometimes) have one `if` after the loop while I only evaluate one condition per iteration. – example Mar 22 '14 at 02:27
  • Ahh Yes I see now, I was confused by the While (true). I never thought of using a loop where it's always true and then putting the if conditionals with breaks inside it. I think with my current knowledge of C++ this seems like my best bet for now and probably what I was looking for. Thanks. – Wallboy Mar 22 '14 at 02:38
3

This looks like a perfectly reasonable use of goto to me.

There's no spaghetti logic in your code, and don't let the naysayers brainwash you into their lies.

Your alternative is to move the loop and the ensuing conditional into their own function, and return from that function. You could use a lambda to keep all the logic inline:

[&]() {
    while (begIt != endIt)
        if ((*begIt).member == someObject.member){
            // Do these statements
            return;
        }
        ++begIt;
    }
    if (begIt == endIt){ // We must have not found an equal member
        // So do these statements
    }
}();

// ...

You can likely shorten your loop logic using C++'s standard algorithms, anyway.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • Awaiting the downvote explanation that will likely never come. – Lightness Races in Orbit Mar 22 '14 at 01:38
  • *This looks like a perfectly reasonable use of goto to me.* This is against the grain of modern software engineering and OP or novice programmers shouldn't be encouraged to use them. If you want to say this in a more qualified fashion (since I do agree this is one of the hardest blocks of code to write in structured programming without a goto) I'll remove. – djechlin Mar 22 '14 at 02:01
  • @djechlin: "It's against the grain" is not an argument. It is baseless mantra. If you want to present a counter-argument for _this_ scenario, _you_ say it in a more qualified fashion. Blindly following trends is not useful. – Lightness Races in Orbit Mar 22 '14 at 02:24
  • Please refer to discussion in comments on my answer. Please do not repeatedly refer to 1000 word articles on the topic as "baseless mantra," as if repeating a mantra or something. – djechlin Mar 22 '14 at 02:26
  • 1
    @djechlin: You're once again supposing that the popularity of something, or its profit margin, or the number of words written on it, somehow inherently makes it right or proper. Please come back when you have a good argument on why this is not a viable solution for the stated problem. Generalised rhetoric is _not_ a good argument. – Lightness Races in Orbit Mar 22 '14 at 02:40
  • The good argument is made of those words though. I would say you have to read them for the argument to be in your mind, but you've already told me not to presume you haven't read something. Enjoy your downvote, I guess. – djechlin Mar 22 '14 at 02:46
  • 1
    @djechlin if your downvote is based on personal issues, then something is clearly wrong here. The answerer made a very valid point that `goto` hate is simply repeated without any thought given, which you seem to be confirming alright. – Bartek Banachewicz Mar 22 '14 at 12:53
  • @BartekBanachewicz please see the discussion under my answer. In it is cited an entire book on best practices in structured programming, including a lengthy discussion on goto, an essay on goto including several ways to avoid it and a qualified but firm recommendation against using it, and one example of a large successful corporation whose coding standards specifically exclude it. I am baffled by how you and Lightness continue insisting that the amount of thought and reasons applied simply qualify as "no thought given" or "repeating a mantra." What more do you want? – djechlin Mar 22 '14 at 14:15
  • @BartekBanachewicz might I suggest that "goto-hate"-*hate* is simply repeated as a mantra with no thought given, and any time someone who argues such as you sniffs an argument against goto you simply sound the trumpets, "here come the goto mantras! Ignore the reasons against using goto, they will not be thought out or novel!" I'm completely baffled here as to what further types of evidence against using goto I can give and how your seeming laziness to read *anything* I have supplied constitutes "my not having given any thought." – djechlin Mar 22 '14 at 14:17
  • @djechlin: I never said the book was repeating a mantra; I said _you_ are, by citing it without qualification. You can't apply _any_ language feature to a general argument without taking into consideration the specifics of the scenario at hand. And you need a reason not to use something, not a reason to use it. The core of the matter here is that **your `bool` approach is _exactly_ as "spaghetti" as the `goto`, if not more**. You keep ignoring that argument because it doesn't fit in with your religious beliefs. Also, you're acting kind of childish which is a shame. – Lightness Races in Orbit Mar 22 '14 at 14:30
  • @LightnessRacesinOrbit Please see the cited essay or book for reasons not to use goto. Please see my previous comments explaining these reasons are in these resources. Please also see my previous comments explaining my consternation in recommending you to read them. If you want to discuss my answer please do so in the comments on my answer, where I may be free to accept a downvote and ignore them (and *that* will be for so-called "personal reasons"). – djechlin Mar 22 '14 at 14:33
  • @LightnessRacesinOrbit There is a mathematical theorem which states that no angle may be trisected using ruler and compass. This is true for all angles. It need not take into account anything specific about the angle at hand. I think this is the concept you don't understand - *that it's possible for a rule not to have exceptions,* and this does not make those who understand the rule close-minded, repeating a mantra, etc. I'm not regurgitating an essay to you in these comments, however. Sorry. – djechlin Mar 22 '14 at 14:36
  • @djechlin: Yes, it is possible. Regardless, this is not one of those cases. I'm not asking you to regurgitate: the only thing you need to do is explain how your `bool` is better than the `goto` in this case. It should take no more than three sentences. Unfortunately you've opted to spend several hundred sentences acting like this, instead. So, I think we're done here. – Lightness Races in Orbit Mar 22 '14 at 17:01
  • @LightnessRacesinOrbit Firstly, no, I *don't* need to do that. As explained in my earliest comments, I'm supplying a way to do this without using goto. The OP may be working at a company where goto is prohibited or in a class where goto is prohibited, in which case my code is "better" *because it is allowed*. This is consistent with the OP's question. Secondly, it is better because it does not use goto and therefore avoids the problems that come with and are unique to goto. I've explained to you how to educate yourself on those problems several times already, so it's up to you from here. – djechlin Mar 22 '14 at 20:51
  • @djechlin: Refusal to acknowledge anything I'm telling you is boring. You _do_ need to back up your assertions with facts, and genericised mantra is not facts. I have given you several opportunities to defend your position for this specific case, and you've passed up on each one. And now you've decided again that I'm not fully aware of the typical arguments against `goto`, despite the fact that we've already covered that lie several times. Finally, "my version is better because yours is not allowed" is ridiculous when such a restriction was never stated. – Lightness Races in Orbit Mar 22 '14 at 21:53
  • @LightnessRacesinOrbit The question title is, "How to rewrite this without the use of goto." You can view it [here](http://stackoverflow.com/questions/22572285/how-to-rewrite-this-without-the-use-of-goto). If someone works at a company or is taking a class in which goto is not allowed, they may click this question. Since SO questions/answers are for the benefit of future viewers, and even possibly the present viewer, who asked the question already quoted in this comment, it is correct to post my answer. – djechlin Mar 22 '14 at 22:55
  • @LightnessRacesinOrbit I don't know what sorts of true things you consider facts, apparently none of the ones I've posted so far count. Sorry, you're on your own. – djechlin Mar 22 '14 at 22:57
1

See Steve McConnell's article for a discussion of ways to refactor gotos. I agree you have one of a few cases that (without C stdlib idioms) are harder to refactor than most intro programming textbooks would suggest, but it's not that hard to refactor and still better to do so.

I agree the above solution that better uses the standard library is best. A standard pattern that works in all languages (that is pure structured programming), is to create a bool foundMatch = false, set it when you find it, and check in your code between the while loop and the goto's label.

djechlin
  • 59,258
  • 35
  • 162
  • 290
  • 1
    This is no better than the `goto`. – Lightness Races in Orbit Mar 22 '14 at 01:40
  • @LightnessRacesinOrbit I believe getting into that argument would be outside the scope of the question. – djechlin Mar 22 '14 at 01:41
  • On the contrary, this question _is_ that argument. – Lightness Races in Orbit Mar 22 '14 at 01:42
  • @LightnessRacesinOrbit I believe the question was "how to rewrite this using goto," not "should one use goto." Similarly if I ask for advice on how to do something in Java I don't expect to get into an argument on whether there are better languages. – djechlin Mar 22 '14 at 01:43
  • @LightnessRacesinOrbit nonetheless, I won't disappoint. Firstly, in many code bases using goto is *illegal.* The code will not check in. I know you're thinking those companies are probably idiotic. One such company is my former company Bloomberg, and you can argue with their billions of dollars of profit how they're clearly making terrible engineering decisions that are only making them billions of dollars a year if you like. The OP may have such a consideration. If not, other visitors to this question *may* need this information. – djechlin Mar 22 '14 at 01:49
  • @LightnessRacesinOrbit furthermore, I agree that there are more canonical solutions using std. That's why I upvoted that answer. Nonetheless in the spirit of StackOverflow my answer is less good but still valid and should receive maybe one or two, but fewer, upvotes. Therefore, I posted it. – djechlin Mar 22 '14 at 01:50
  • If `the question was "how to rewrite this using goto," not "should one use goto"`, then why did you decide to write an answer debasing the `goto` approach and instead proposing your preferred alternative? – Lightness Races in Orbit Mar 22 '14 at 01:50
  • Also, I stopped reading when you deemed it useful or logical to suggest that some behemothic corporation's balance sheet has anything at all to do with this coding style decision. – Lightness Races in Orbit Mar 22 '14 at 01:51
  • @LightnessRacesinOrbit now for the question of using goto itself. In the year 2014 it is completely wrong to use goto. Yes, there are cases where in an isolated 20-50 line snippet of code the goto solution can be more elegant but this is myopic to the entire practice of software engineering. Not using goto also communicates that code is written in a modern style and can be read with a modern speed. If I see a goto in code, not only do I slow down to read that section, I also *slow down* to read the *entire* file, awaiting other little subtle patterns the programmer left me behind to discern. – djechlin Mar 22 '14 at 01:54
  • @LightnessRacesinOrbit if the coding style of successful corporations is not valid evidence to you, might I inquire what kind of evidence you do accept besides vague opining? – djechlin Mar 22 '14 at 01:55
  • You seem to be the sort of person who uses logic like "the digits in the current year are '2', '0', '1' and '4', therefore you should not use `goto`", and "a corporation that does not use `goto` is successful, therefore you should not use `goto`" (I think you'll find the success of the company has _nothing_ to do with that). This is a shame, especially since you go on to accuse _me_ of holding only airy arguments. Made even worse when your proposed solution is precisely as prone to spaghetti code. Please return to this thread when you have something concrete to bring to the table. – Lightness Races in Orbit Mar 22 '14 at 01:56
  • @LightnessRacesinOrbit Sure. Please read Steve McConnell's *Code Complete*, for instance. Would it be too sarcastic for me to suggest Dijkstra's paper "Gotos Considered Harmful"? But as far as evidence that fits in a comment box goes, "the cumulative software experience of the last 3 decades" (that does happen to bring the year to 2014, a year whose digits are indeed '2', '0', '1', '4') will have to do. – djechlin Mar 22 '14 at 01:59
  • @LightnessRacesinOrbit e.g. http://www.stevemcconnell.com/ccgoto.htm is an extensive discussion. The author articulates a minority of a minority of cases where it is probably preferable to write in one of several goto-less ways, but maybe acceptable with clear documentation for what it's doing. – djechlin Mar 22 '14 at 02:04
  • Please stop suggesting that I haven't read all these things before. It's possible to disagree with djechlin without being ignorant of the facts (and, in this case more relevantly, established mantra from known names). – Lightness Races in Orbit Mar 22 '14 at 02:09
  • @LightnessRacesinOrbit You asked for "something concrete." What more do you want? A block of concrete? – djechlin Mar 22 '14 at 02:10
  • @LightnessRacesinOrbit It's possible to disagree, but generally if you enter a discussion it's assumed you will respond to evidence contrary to your opinion or in general do more than either 1) mock my arguments or 2) say you don't care about them. But, should anyone else bother to read this thread they'll see a book, a linked article, examples of code bases and argument on my side, and... mocking each of my arguments on your side. Fine by me. – djechlin Mar 22 '14 at 02:15
  • @LightnessRacesinOrbit oh, and let's not forget this one! http://news.cnet.com/8301-13579_3-57619510-37/apple-finally-fixes-gotofail-os-x-security-hole/ – djechlin Mar 22 '14 at 02:16
  • I haven't "mocked" anything you've said; I've simply identified your counter-arguments as being irrelevant. There is no need to get defensive/personal. – Lightness Races in Orbit Mar 22 '14 at 02:25
0

AFAIK the idea of using goto has been dead for a while apart from maybe in Windows batch scripts and certainly not in C++ where we have all kinds of flow control magic. This is done primarily to improve code readability and avoid ending up with spaghetti code which is code with so many gotos and labels flying around that it's utter hell to mke head nor tail of, let alone maintain. If you want to jump out of the loop I the break command is what you want. Like so:

bool not_broken;
not_broken = true;
while (begIt != endIt)
    if ((*begIt).member == someObject.member){
        // Do these statements
        not_broken=false;
        break; // quit out of while loop
    }
    ++begIt;
}
if (not_broken && begIt == endIt){ // We must have not found an equal member
    // So do these statements
}
// code continues...

I wouldn't be overly concerned about knowing that begIt wont equal endIt but if this really bothers you then you could set a bool just before you break and use the logical and operator && to check whether or not the while loop was broken. It is important that the bool is first in the if as this will result in the begIt and endIt not being compared when the bool is false.

nettux
  • 5,270
  • 2
  • 23
  • 33
  • I had the break; in place of the goto originally, but I was just bothered by the If condition after the loop knowing that it will fail all the time if we came from the break so why even check it then. And yes I thought of just setting up a "flag" variable where in would set it to true in we found an equal member and then check for that in the if following the loop, but the goto just completely eliminated the need for that. – Wallboy Mar 22 '14 at 02:09
  • Using a goto may be marginally more efficient but in my opinion it's dirtier and less readable and readability matters. Thinking over this a little more I think this would be better with the while loop in it's own function. – nettux Mar 22 '14 at 02:23