Closed ThePhD closed 5 years ago
This one will also require implementation before it gets anywhere, since it seems EWG is mostly unconvinced. (The latest papers from Alan Talbot were about "loop exit blocks", which does the same thing but doesn't allow you to jump multiple scopes.)
I was personally informed that EWG hates most of the alternatives. Presenting this paper at this time is a bad idea. Shelf it, maybe still for C++23, but for later after implementation experience.
To be honest that's the kind of job for which I would still use goto
, if only it was available in constexpr
functions :'(
It'd likely be useful to point out Rust and Go's solutions to the problem,
fn main() {
'a: loop {
'b: loop {
break 'a;
}
}
}
func main() {
a: for {
b: for {
break a;
}
}
}
(Go is as I remember it, not guaranteed correct)
@Morwenn That's part of the motivation: goto
is hard to implement in constexpr processors because they currently do AST execution and arbitrarily jumping in those is a nightmare. Most implementers say its doable but not worth the effort.
Labeled loops, on the other hand, I have confirmed with at least 2 different frontend implementers are trivially-doable in constexpr
. Plus, most goto
s I have seen -- aside from C code -- has been for jumping out of multiple loops.
@ubsan We wanted to borrow Swift's syntax here for C++, ending up with a grammar like:
while (condition) label-name { ... }
do { ... } while (condition) label-name;
for (init; condition; incr) label-name { ... }
for (type-seq var : expr ) label-name { ... }
with break label-name;
jumping out to that level, or continue label-name;
jumping to the end of that loop and continuing its next iteration.
I was about to give you a bit of motivation but I realized that the algorithms from <algorithm>
in libc++ that use goto
aren't apparently trivially convertible to algorithms using labeled loops (those algorithms being std::stable_partition
and std::nth_element
). And it's unfortunate that those algorithms use goto
because they will be required to be constexpr
in C++20.
On the other hand, there is a pull request proposing to replace a break_outer
variable by a simple use of goto
in gfx/cpp-TimSort which is a popular implementation of TimSort in C++. I guess that it can be used as a real-world example. Another C++ implementation of TimSort [uses goto
too] but unfortunately it can't be replaced by labeled loops in that case.
I found myself wanting to use goto
once in an algorithm, and once again it doesn't fall into the category of labeled loops.
Ironically enough, most uses of goto
I've found aren't to break out of inner loops ^^'
@ThePhD Swift's syntax is nasty af tho; not being able to see the labels at the start of the loop is really unfortunate.
I mean, we can move the labels to the start of the loop? I've got no real problems with that.
You could most likely reuse a goto
kind of label in front of a loop, which has a few advantages:
break
label and continue
label are surely uncontroversial).outer: while (...) {
inner: while (...) {
if (condition) {
break outer;
}
}
}
The only drawback I see would be people complaining that it acts as goto label
with label:
declared after the loop, but it doesn't feel like a huge drawback.
EDIT: I just discovered that this syntax matches the one in Java, so it wouldn't be surprising for people who have already been exposed to labeled loops in Java.
Has no paper number now because unsubmitted papers from the old system went straight to hell.
This paper is a lost cause.
Maybe in 10 years.
From another thread:
FWIW, I was tempted to write the paper you wanted to write. Discussion amongst a few members of the Committee made it painfully clear that the paper would go Nowhere, even with motivating examples, because 7+ proposals in the before-times already came around and effectively soured the taste of such in everyone's mouth on top of the already violent disposition against additional flow control statements.
You're better off just using "goto" for now, however heinous many may consider it. Maybe wait until C++32, when the ideas died down for a while and we have more complex iteration techniques after building up large amounts of ranges algorithms that might require more complex algorithm internals where breaking out of 2+ loops or similar would be justified.
Also note that constexpr goto
is possible but deemed "hella effort", so the proposal hasn't gone anywhere for that just yet.
Bring it back in 15 years x)
Unpopular opinion: This makes it easier for non-advanced developers to write horrible, barley-readable code, and may encourage them to make longer and more complex functions instead of refactoring and extracting those loops into separate functions
...
for (int i = 0; i < 4; ++i)
if(self_documenting_function_name(i))
break;
...
auto self_documenting_function_name(int const num) -> bool
{
// some explanations since you've dug this deep!
for (int i = 0; num > 2 && i < 4 ; ++i)
if(check_func(num, i))
return true;
return false;
}
Ideal syntax:
Goal: to enable better control of moving in and out of nested loops, without having to create catch-all lambdas which scale poorly for templated code. It also is easier to implement for
constexpr
in almost all currentconstexpr
engines. The usage would be like this: