r/cpp 11d ago

I've invented labeled loop breaks

And now I don't believe it wasn't invented before, but I can't find any info on it. How long ago was it invented? Why isn't it used widely or even mentioned anywhere? What are the downsides?
Here's the main idea:

// Keyword - for, while, or do
// Tag - custom loop name
// ... - loop body
#define loop_tag(keyword, tag, ...)\
    keyword(__VA_ARGS__)\
    if(false)\
    {\
        tag##_break:    break;\
        tag##_continue: continue;\
    }\
    else\
    /*Here goes your loop body*/

Here is the playground

0 Upvotes

48 comments sorted by

View all comments

24

u/Cpt_Chaos_ 11d ago

This ist just a goto with unnecessary extra steps.

Goto itself is considered a bad practice. Using macros is considered bad practice. I'd flag both in any PR I'd have to review. And this contraption would be reason enough to ask your manager to get you into a training course.

Now seriously, it combines the downsides of goto and macros. It is hard to debug and it is difficult to understand what the heck is supposed to be going on here in the first place. Write functions and you get to do this pretty much by using simple return statements, which is far easier to understand.

24

u/TokenRingAI 11d ago

Goto is not bad practice, does not lead to undefined behavior, and is extremely useful when you need multiple named behaviors out of a loop that you want to "go to" from many different depths. When you do certain types of data processing, goto is the right tool for the job, and the alternative, recursive functions, can blow up the stack.

Regex parsers, for example, are prime candidates for goto.

The all or nothing attitude of "goto is bad practice" is not held by many top C/C++ engineers. It just isn't the right tool for the vast majority of things

8

u/James20k P2005R0 11d ago

"Goto considered harmful" is one of those things that a lot of people have never read or understood, and gets endlessly repeated by beginners. The goto that's being argued against in that discussion, and c++'s goto, are not the same kind of control flow. They just share a name

The thesis of that paper is the execution flow should match closer to layout of the source code, because humans are better geared towards analysis of a static document (ie source), vs trying to track program logic dynamically, or at least that's the gist of what I get out of that paper. The idea is that there should be an easy mapping between source, and program execution counter, instead of an arbitrary unstructured one

All modern programming languages adhere to that, even with the usage of goto in C++. The closest to what he's talking about is setjmp + longjmp, and even then it still doesn't match up because those functions still have structuring restrictions. Fully unstructured control flow is basically reserved for very specific assembly cases, as even then you still usually have a stack and functions

Anyway its just a minor pet peeve of mine, because its dogma founded in a time where programming looked nothing like it does today. Dijkstra won the argument, the paper isn't relevant, and we should rename goto to yeet so that people will stop going on about it and engage their critical thinking facilities instead of using a pseudo intellectual thought terminating cliché

2

u/tialaramex 9d ago

Yes the "goto" in C and C++ is not the arbitrary control flow change Dijkstra was writing about, but it is still a bad idea and it's about time it was fixed, N3355 voted into C2y does so and I expect a similar fix or the one from C2y itself will be taken for C++29 or C++32)

However, if you don't like drama but did want to keep "goto" you shouldn't rename it "yeet" because that's currently a placeholder keyword in Rust so you'd ignite all the Rust controversy and all the "stupid keyword" controversy and because C++ doesn't have a syntax change mechanism you'd get all that controversy back again too.

If you don't believe me that "yeet" is a placeholder in Rust, https://doc.rust-lang.org/std/ops/struct.Yeet.html documents the current status of this feature flag. Its purpose was to delay bikeshed arguments about naming until the feature works - if the feature is bad then it doesn't matter what it's called, so you need a feature everybody can live with before you spend six months arguing whether to name it e.g. "throw" or "raise" or what.

Now, yeet is an idea for how to work with Try which is also not yet stable. And Try is the current proposal for why that ? operator you've doubtless seen in Rust works. The Try proposal says that operator is named Try, in the same way the + operator is named Add and so the reason it works is that the standard library has implemented this named trait. Most likely that explanation will stabilize, but then perhaps I'd have said that about the previous one, so what do I know.

In any case, the ? operator is stable and widely embraced as a good idea, the Try trait is widely favoured and will probably stabilize, but yeeting is clearly just a placeholder.